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