python-面向对象
1,编程范式
- 面向对象编程实际上就是一种编程范式。
- 编程是程序员用 特定的语法 + 数据结构 + 算法 组成的代码来告诉计算机如何执行任务的过程。
- 两种最重要的编程范式分别是
面向过程编程
面向对象编程
2,面向过程编程
面向过程:核心是过程二字,过程指的是解决问题的步骤,相当于设计一条流水线,机械式的一种思维方式
优点:复杂的问题流程化,进而简单化
缺点:可拓展性差,如果要修改,牵一发动全身
"""实现一个用户注册功能""" # 1.用户输入 # 2.验证是否符合标准 # 3.注册 def enter(): username = input('请输入用户名>:').strip() password = input('请输入密码>:').strip() return { 'username': username, 'password': password } def check(user_info): is_valid = True if len(user_info['username']) == 0: print('用户名不能为空') is_valid = False if len(user_info['password']) < 6: print('密码不能少于6个字符') is_valid = False return { 'is_valid': is_valid, 'user_info': user_info } def register(check_info): if check_info['is_valid']: import json with open('users.txt', 'w', encoding='utf-8') as f: json.dump(check_info['user_info'], f) print('注册成功') def main(): user_info = enter() check_info = check(user_info) register(check_info) if __name__ == '__main__': main()
如果添加一个邮箱验证的新功能,牵一发动全身,基本上都需要修改功能:
3,面向对象编程
面向对象:核心是对象
对象是特征与技能的结合体
优点:可拓展性高
缺点:编程复杂度高
应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用。
面向对象的三大特性
封装: 如何组织类或模块,让封装的类或组件,尽量只负责一个领域的工作.
继承: 复用方式之一,概念形成统一。通过继承可以管理多个概念
多态: 类、方法等的行为不同的做法。目标一致,实现的方式不同
python中一切皆对象
而在python3中统一了类与类型的概念(类型就是类)
即便是对于列表,列表也是一个类,也可以调用类下面的函数
l1 = [1, 2, 3] # l = list[1, 2, 3] l2 = [] l1.append(4) # == list.append(l1, 4) 实际上就相当于list下面调用类的函数(append), #把l1当作第一个参数传进来,把4当作第二个参数传进来 print(l1) # 类下面(list是一个类),有很多的功能来给对象使用,但是一般我们不会调用list.append(l1, 4)来 # 传入对象和参数,我们会调用自己,更明确,更简单一点
4,定义类与实例化出对象
类就是一系列对象相似的特征与技能的结合体。类别,分类。
(特征:变量,技能:函数;实际上类内部就是变量定义和函数定义)
作用:进一步提升函数的复用性,拓展性。面向对象,贴近人的思想。
注意:站在不同的角度,得到的分类是不一样的。
在现实世界当中:一定先有对象,后有类。
在程序中:一定得先定义类,后调用类来产生对象。
站在认类的角度定义类和对象
站在学生的角度,大家都是学生 在现实世界中: 对象1:张三 特征: 学校='school' 名字='张三' 性别='女' 年龄=18 技能: 学习 吃饭 睡觉 对象2:李四 特征: 学校='school' 名字='李四' 性别='男' 年龄=28 技能: 学习 吃饭 睡觉 对象3:王五 特征: 学校='school' 名字='王五' 性别='女' 年龄=38 技能: 学习 吃饭 睡觉 总结现实中学生的学生类 相似的特征: 学校=’school‘ 相似的技能 学习 吃饭 睡觉
站在程序的角度定义类和对象
# 先定义类 class Student: school = 'School' def learning(self): print('is learning') def eating(self): print('is eating') def sleep(self): print('is sleeping') # 后产生对象 stu1 = Student() stu2 = Student() stu3 = Student() print(stu1) print(stu2) print(stu3)
运行结果
<__main__.Student object at 0x0315C490> <__main__.Student object at 0x0315C8D0> <__main__.Student object at 0x0315C970> # 我们可以得到学生对象和对应的地址
5,如何使用类
先定义类
# 先定义类 class Student: school = 'School' # 数据属性 def learning(self): # 函数属性 print('is learning') def eating(self): # 函数属性 print('is eating') def sleep(self): # 函数属性 print('is sleeping')
1,查看类的名称空间
# 查看类的名称空间: print(Student.__dict__) print(Student.__dict__['school']) print(Student.__dict__['learning'])
运行结果
{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} School <function Student.learning at 0x0309A390>
2,查看属性
# 查看属性 print(Student.school) # ==print(Student.__dict__['school']) print(Student.learning) # ==print(Student.__dict__['learning']) print(Student.eating) # ==print(Student.__dict__['eating'])
运行结果
School <function Student.learning at 0x0309A390> <function Student.eating at 0x0309A3D8>
3,增加属性
# 增加属性 Student.country = 'China' print(Student.__dict__) print(Student.country)
运行结果
{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'country': 'China'} China
4,删除属性
# 删除属性 del Student.country print(Student.__dict__)
运行结果
{'__module__': '__main__', 'school': 'School', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
5,改属性
# 改属性 Student.school = 'School*' print(Student.__dict__)
运行结果
{'__module__': '__main__', 'school': 'School*', 'learning': <function Student.learning at 0x0309A390>, 'eating': <function Student.eating at 0x0309A3D8>, 'sleep': <function Student.sleep at 0x0309A420>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
类的第一用途是对类进行操作,第二大用途是实例化产生一个一个的对象
6,如何使用对象(__init__方法)
通过 __init__ 方法用来为对象定制对象自己独有的特征
class Student: school = 'School' # stu1,'王二丫', '女', 18 def __init__(self, name, sex, age): self.Name = name self.Sex = sex self.Age = age # stu1.Name = '王二丫' # stu1.Sex = '女' # stu1.Age = 18 def learning(self): print('is learning') def eating(self): print('is eating') def sleep(self): print('is sleeping') # 后产生对象 stu1 = Student('王二丫', '女', 18) # Student.__init__(stu1,'王二丫', '女', 18) # 加上__init__方法后,实例化的步骤 # 1,先产生一个空对象 # 2,触发方法Student.__init__(stu1,'王二丫', '女', 18)(这就是一个函数) print(Student.__init__) # 先产生一个叫stu1的空对象,然后将stu1,加上后面三个参数组成四个参数传给__init__
###
<function Student.__init__ at 0x01DE9390>
1,查看属性
# 查看属性 print(stu1.__dict__) # 上面定义好了以后将产生一个名称空间,将这些参数传到里面,形成一个字典 print(stu1.Name) ### {'Name': '王二丫', 'Sex': '女', 'Age': 18} 王二丫
2,改属性
# 改属性 stu1.Name = '王二麻' print(stu1.Name) ### 王二麻
3,增加属性
# 增加属性 stu1.Friend = '李二麻' print(stu1.__dict__) ### {'Name': '王二麻', 'Sex': '女', 'Age': 18, 'Friend': '李二麻'}
4,删属性
# 删属性 del stu1.Friend print(stu1.__dict__) ### {'Name': '王二麻', 'Sex': '女', 'Age': 18}
stu2 = Student('李三炮', '男', 38) print(stu2.Name) print(stu2.Sex) print(stu2.Age) ### 李三炮 男 38
7,属性查找与绑定方法
对象:特征与技能的结合体
类:类是一系列对象相似的特征与技能的结合体
class Student: school = 'School' # stu1,'王二丫', '女', 18 def __init__(self, name, sex, age): self.Name = name self.Sex = sex self.Age = age # stu1.Name = '王二丫' # stu1.Sex = '女' # stu1.Age = 18 def learning(self): print('%s is learning ' % self.Name) def eating(self): print('%s is eating' % self.Name) def sleep(self): print('%s is sleeping' % self.Name) # 后产生对象 stu1 = Student('王二丫', '女', 18) stu2 = Student('李三炮', '男', 38) stu3 = Student('张铁蛋', '男', 48) print(stu1.__dict__) print(stu2.__dict__) print(stu3.__dict__) ### {'Name': '王二丫', 'Sex': '女', 'Age': 18} {'Name': '李三炮', 'Sex': '男', 'Age': 38} {'Name': '张铁蛋', 'Sex': '男', 'Age': 48}
1,类中的数据属性
类中的数据属性:是所有对象共有的。
# 类中的数据属性:是所有对象共有的 print(Student.school, id(Student.school)) print(stu1.school, id(stu1.school)) print(stu2.school, id(stu2.school)) print(stu3.school, id(stu3.school)) ### School 17292672 School 17292672 School 17292672 School 17292672
2,类中的函数属性
类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当第一个参数传入(传给self)
# 类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法,对象调用绑定方法时,会把对象本身当第一个参数传入(传给self) print(Student.learning(stu1)) print(Student.learning(stu2)) print(Student.learning(stu3)) print(Student.learning) print(stu1.learning) # 这里绑定方法还是learning函数,后面跟上它的内存地址,也可以调用 print(stu2.learning) print(stu3.learning) stu1.learning() #把对象本身当第一个参数传给self ### 王二丫 is learning None 李三炮 is learning None 张铁蛋 is learning None <function Student.learning at 0x0115A420> <bound method Student.learning of <__main__.Student object at 0x0358C8D0>> <bound method Student.learning of <__main__.Student object at 0x0358C8F0>> <bound method Student.learning of <__main__.Student object at 0x0358C950>> 王二丫 is learning
当对象在访问一个属性的时候,会先从自己的名称空间里面去找,然后去类里面去找,再到父类里面去找,不会去全局里面去找。
# 当对象在访问一个属性的时候,会先从自己的名称空间里面去找,然后去类里面去找,再到父类里面去找,不会去全局里面去找。 stu1.x = 'from stu1' Student.x = 'from School class' print(stu1.x) ### from stu1
8,面向对象可拓展性总结
通过面向对象,可以把数据与处理数据的功能捆绑在一起
那么为何面向对象可拓展性高?
class Chinese: country = 'China' # 可以随时加上变量(特征),而不需要改动其他地方 def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def eat(self): # 也可以直接添加一个函数(技能) print('%s is eating'% self.name ) p1 = Chinese('egon', 18, 'male') p2 = Chinese('alex', 38, 'female') p3 = Chinese('wpq', 48, 'female') print(p1.country) print(p1.eat())
随时加上特征和技能,而不需要改动其他的地方
9,对象互访问与交互
1,想要对象能公共访问,须定义类属性,如果仅仅定义自身self属性,那么每个对象访问都是独立访问的
# 便携一个学生类,产生一堆的学生对象,并且要求有一个计数器(属性),统计总共示例了多少个对象 # 解答 class Student: count = 0 # 需要所有对象都能访问的参数,所以设置在类属性当中 def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age Student.count += 1 def eat(self): print('%s is eating breakfast' % self.name) stu1 = Student('王一丫', '女', '18') stu2 = Student('王二丫', '女', '18') stu3 = Student('王三丫', '女', '18') print(Student.count) ### 4 #注意点 class Student: count = 0 # 需要所有对象都能访问的参数,所以设置在类属性当中 def __init__(self, name, sex, age): self.name = name self.sex = sex self.age = age # self.count += 1 # 这里没有定义__init__ count对象,传类中的参数给count,这里定义的count参数是传给每个对象独有的,也就是说,这么定义,每个对象不能公共访问,就会造成计数一直都是1 # 应该定义一个类属性 Student.count += 1 def eat(self): print('%s is eating breakfast' % self.name) stu1 = Student('王一丫', '女', '18') stu2 = Student('王二丫', '女', '18') stu3 = Student('王三丫', '女', '18') print(stu1.count) # 每一个对象访问count都是相互独立的,故都是1 print(stu2.count) print(stu3.count) print(stu1.__dict__) # 每个对象里面的count都相互独立 print(stu2.__dict__) print(stu3.__dict__) print(Student.count) # 所以记录对象不能通过大家自己独有的方式去记录,要通过大家共有的方式去记录 # 在__init__下面定义一个类属性,Student.count += 1 ### 在__init__中定义self.count += 1,结果一直都是1 在__init__中定义Student.count += 1,结果就可以随着对象的改变而改变了,结果为3
2,如何实现不同类对象之间的交互
# 如何让对象之间交互完成事情 """ 实例二 模仿LOL定义两个英雄类 要求: 英雄需要又昵称,攻击力,生命值等属性 实例化出两个英雄对象 英雄之间可以互殴,被殴打的一方掉血,血量小于0则判定死亡 """ class Gailen: city = 'Demacia' def __init__(self, nickname, life_value, aggressivity): self.nickname = nickname self.life_value = life_value self.aggressivity = aggressivity def attack(self, enemy): enemy.life_value -= self.aggressivity class Riven: city = 'Noxus' def __init__(self, nickname, life_value, aggressivity): self.nickname = nickname self.life_value = life_value self.aggressivity = aggressivity def attack(self, enemy): enemy.life_value -= self.aggressivity gailen = Gailen('暗影之拳', 120, 30) riven = Riven('锐雯雯', 100, 40) print(riven.life_value) gailen.attack(riven) print(riven.life_value)