您现在的位置是:网站首页> 编程资料编程资料
Python面向对象编程(二)_python_
2023-05-26
403人已围观
简介 Python面向对象编程(二)_python_
一、对象的继承
Python中支持一个类同时继承多个父类
class Parent1: pass class Parent2: pass class Sub1(Parent1, Parent2): pass
使用__bases__方法可以获取对象继承的类
print(Sub1.__bases__) # (, )
在Python3中如果一个类没有继承任何类,则默认继承object类。
print(Parent1.__bases__) #('object'>,)1、类的构造函数继承__init__():
- 子类需要自动调用父类的方法:子类不重写__init__()方法,实例化子类后,会自动调用父类的__init__()的方法。
- 子类不需要自动调用父类的方法:子类重写__init__()方法,实例化子类后,将不会自动调用父类的__init__()的方法。
- 子类重写__init__()方法又需要调用父类的方法:需要使用super关键词。
2、继承关系中,对象查找属性的顺序
对象自己——>对象的类——>父类——>父类。。。
class OldboyPeople: """由于学生和老师都是人,因此人都有姓名、年龄、性别""" school = 'oldboy' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class OldboyStudent(OldboyPeople): def choose_course(self): print('%s is choosing course' % self.name) class OldboyTeacher(OldboyPeople): def score(self, stu_obj, num): print('%s is scoring' % self.name) stu_obj.score = num stu1 = OldboyStudent('tank', 18, 'male') tea1 = OldboyTeacher('nick', 18, 'male') print(stu1.school) # oldboy print(tea1.school) # oldboy print(stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male'} tea1.score(stu1, 99) # nick is scoring print(stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male', 'score': 99}二、类的派生
子类中新定义的属性的这个过程叫做派生,子类在使用派生的属性时始终以自己的为准。
1、派生方法一(类调用)
指名道姓访问某一个类的函数:该方式与继承无关
class OldboyPeople: """由于学生和老师都是人,因此人都有姓名、年龄、性别""" school = 'oldboy' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender class OldboyStudent(OldboyPeople): """由于学生类没有独自的__init__()方法,因此不需要声明继承父类的__init__()方法,会自动继承""" def choose_course(self): print('%s is choosing course' % self.name) class OldboyTeacher(OldboyPeople): """由于老师类有独自的__init__()方法,因此需要声明继承父类的__init__()""" def __init__(self, name, age, gender, level): OldboyPeople.__init__(self, name, age, gender) self.level = level # 派生 def score(self, stu_obj, num): print('%s is scoring' % self.name) stu_obj.score = num stu1 = OldboyStudent('tank', 18, 'male') tea1 = OldboyTeacher('nick', 18, 'male', 10) print(stu1.__dict__) # {'name': 'tank', 'age': 18, 'gender': 'male'} print(tea1.__dict__) # {'name': 'nick', 'age': 18, 'gender': 'male', 'level': 10}2、派生方法二(super)
- 严格以继承属性查找关系
- super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
- super().__init__(不用为self传值)
- super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以简写为super()。
class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def choose_course(self): print('%s is choosing course' % self.name) class OldboyStudent(OldboyPeople): def __init__(self, name, age, sex, stu_id): # OldboyPeople.__init__(self,name,age,sex) # super(OldboyStudent, self).__init__(name, age, sex) super().__init__(name, age, sex) self.stu_id = stu_id def choose_course(self): print('%s is choosing course' % self.name) stu1 = OldboyStudent('tank', 19, 'male', 1) super(OldboyStudent,stu1).choose_course() #用子类对象调用父类已被覆盖的方法 print(stu1.__dict__) # {'name': 'tank', 'age': 19, 'sex': 'male', 'stu_id': 1}三、类的组合
类对象可以引用/当做参数传入/当做返回值/当做容器元素,类似于函数对象。
- 组合是用来解决类与类之间代码冗余的问题
组合可以理解成多个人去造一个机器人,有的人造头、有的人造脚、有的人造手、有的人造躯干,大家都完工后,造躯干的人把头、脚、手拼接到自己的躯干上,因此一个机器人便造出来了
class Course: def __init__(self, name, period, price): self.name = name self.period = period self.price = price class OldboyPeople: school = 'oldboy' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class OldboyStudent(OldboyPeople): def __init__(self, name, age, sex, stu_id): OldboyPeople.__init__(self, name, age, sex) self.stu_id = stu_id def choose_course(self): print('%s is choosing course' % self.name) class OldboyTeacher(OldboyPeople): def __init__(self, name, age, sex, level): OldboyPeople.__init__(self, name, age, sex) self.level = level def score(self, stu, num): stu.score = num print('老师[%s]为学生[%s]打分[%s]' % (self.name, stu.name, num)) # 创造课程 python = Course('python全栈开发', '5mons', 3000) linux = Course('linux运维', '5mons', 800) # 创造学生与老师 stu1 = OldboyStudent('tank', 19, 'male', 1) tea1 = OldboyTeacher('nick', 18, 'male', 10) # 组合 # 将学生、老师与课程对象关联/组合 stu1.course = python tea1.course = linux四、多父类继承问题
Python同样有限的支持多继承形式。多继承的类定义形如下例:
class DerivedClassName(Base1, Base2, Base3): . . .
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 。即方法在子类中未找到时,从左到右查找父类中是否包含方法。
1、新式类(MRO)列表
- 继承了object的类以及该类的子类,都是新式类
- Python3中所有的类都是新式类
- 广度优先, 老祖宗最后找。
class G(object): # def test(self): # print('from G') pass class E(G): # def test(self): # print('from E') pass class B(E): # def test(self): # print('from B') pass class F(G): # def test(self): # print('from F') pass class C(F): # def test(self): # print('from C') pass class D(G): # def test(self): # print('from D') pass class A(B, C, D): def test(self): print('from A') obj = A() obj.test() # A->B->E-C-F-D->G-object # from Apython计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,来实现继承的。
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。
print(A.mro()) # A.__mro__ # [, , , , , , , ] for i in A.mro(): print(i) # # # # # # # #
2、super()方法详解
super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
下面的例子可以看到:
- 每个类开始调用是根据MRO顺序进行开始,然后逐个进行结束的。
- 由于因为需要继承不同的父类,参数不一定,所有的父类都应该加上不定参数*args , **kwargs ,不然参数不对应是会报错的。
# 胖子老板的父类 class FatFather(object): def __init__(self, name, *args, **kwargs): print() print("=============== 开始调用 FatFather ========================") print('FatFather的init开始被调用') self.name = name print('调用FatFather类的name是%s' % self.name) print('FatFather的init调用结束') print() print("=============== 结束调用 FatFather ========================") # 胖子老板类 继承 FatFather 类 class FatBoss(FatFather): def __init__(self, name, hobby, *args, **kwargs): print() print("=============== 开始调用 FatBoss ========================") print('胖子老板的类被调用啦!') # super().__init__(name) # 因为多继承传递的参数不一致,所以使用不定参数 super().__init__(name, *args, **kwargs) print("%s 的爱好是 %s" % (name, hobby)) print() print("=============== 结束调用 FatBoss ========================") # 胖子老板的老婆类 继承 FatFather类 class FatBossWife(FatFather): def __init__(self, name, housework, *args, **kwargs): print() print("=============== 开始调用 FatBossWife ========================") print('胖子老板的老婆类被调用啦!要学会干家务') # super().__init__(name) # 因为多继承传递的参数不一致,所以使用不定参数 super().__init__(name, *args, **kwargs) print("%s 需要干的家务是 %s" % (name, housework)) print() print("=====
相关内容
- Python+Turtle绘制可爱的可达鸭_python_
- Python编写条件分支代码方法_python_
- python中format的用法实例详解_python_
- Python面向对象编程(一)_python_
- Python测试框架pytest高阶用法全面详解_python_
- pytest fixtures函数及测试函数的参数化解读_python_
- Python使用Web框架Flask开发项目_python_
- numpy array找出符合条件的数并赋值的示例代码_python_
- Python OpenCV实现任意角度二维码矫正_python_
- Python datacompy 找出两个DataFrames不同的地方_python_
点击排行
本栏推荐
