继承
在子类派生的新方法中如何重用父类的功能
指名道姓
# 方式一:指名道姓 调用某一个类下的函数=》不依赖于继承关系
class OldboyPeople:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def f1(self):
print('%s say hello' %self.name)
class Teacher(OldboyPeople):
def __init__(self,name,age,sex,level,salary):
OldboyPeople.__init__(self,name,age,sex) # 指名道姓,该传几个参数就传几个参数
self.level = level
self.salary=salary
tea_obj=Teacher('egon',18,'male',10,3000)
print(tea_obj.__dict__)
# {'name': 'egon', 'age': 18, 'sex': 'male', 'level': 10, 'salary': 3000}
严格依赖继承--super()
# 方式二:super() 调用父类提供给自己的方法=》严格依赖继承关系
# 调用super()会得到一个特殊的对象,该对象会参照发起属性查找的那个类的mro,去当前类的父类中找属性
class OldboyPeople:
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
def f1(self):
print('%s say hello' %self.name)
class Teacher(OldboyPeople):
def __init__(self,name,age,sex,level,salary):
# super(Teacher,self).__init__(name,age,sex)
super().__init__(name,age,sex) # 调用的是方法,自动传入对象
self.level = level
self.salary=salary
print(Teacher.mro())
# [<class '__main__.Teacher'>, <class '__main__.OldboyPeople'>, <class 'object'>]
tea_obj=Teacher('egon',18,'male',10,3000)
print(tea_obj.__dict__)
# {'name': 'egon', 'age': 18, 'sex': 'male', 'level': 10, 'salary': 3000}
# self.__init__(name,age,sex)
# 因为self严格指向自己,self在Teacher类里面,因此self是一个teacher对象,就进入了一个递归了
---------------------------------------------------------
Traceback (most recent call last):
File "C:/Users/baobao/PycharmProjects/untitled1/hello.py", line 23, in <module>
tea_obj=Teacher('egon',18,'male',10,3000)
File "C:/Users/baobao/PycharmProjects/untitled1/hello.py", line 15, in __init__
self.__init__(name, age, sex)
TypeError: __init__() missing 2 required positional arguments: 'level' and 'salary'
# super()的用法
# 针对Python2,必须这么用,并且super只能用于新式类当中
super(Teacher,self).__init__(name,age,sex)
# 对于python3,可以简写,super什么参数都不用传,直接加括号
super().__init__(name,age,sex)
# __init__(self,...)不用传参self,因为super()得到的是一个对象,自动传入对象
# super会创建一个特殊对象,会参照当前类的MRO,去当前类的父类去找,即从第二个位置往后找,找到OldboyPeople
print(Teacher.mro())
# [<class '__main__.Teacher'>, <class '__main__.OldboyPeople'>, <class 'object'>]
# super()案例
# A和B之间没有继承关系
class A:
def test(self):
print('from A')
super().test() # 参照MRO,去B中找,尽管没有继承关系
class B:
def test(self):
print('from B')
class C(A,B):
pass
obj=C()
obj.test()
# 分析查找顺序
# 1.obj先从自己找,没有
# 2.去C里面找,没有
# 3.按照发起属性查找的那个类的mro往下找下去,发起者是C类,因此参照C去找A
# 重点:super属性查找不能简单的理解为直接去爹(父类)找,参照的是属性查找发起者的mro;因此即便A和B没有继承关系,找完A也能接着去找B
print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
# 4.参照C去找A,找到test,打印from A;紧接着遇到super,当前在A,因此查找当前类的父类;而当前类的父类是属性发起者的MRO规定的(super去找A类的爹参照MRO,而MRO规定A的爹是B)
# 5.super().test()去B找,打印from B
from A
from B
# 强调一下,子类中用父类功能有两种方式,推荐用super
# 哪种都可以用,但是不能混着用
# 指名道姓:和MRO压根没关系,压根不参考MRO
# super:严格依赖MRO,但是不是参考自己的MRO,而是参考属性查找发起者那个类的MRO,去找当前类的父类
class A:
def test(self):
print('from A')
super().test1() # 参照C的MRO,,MRO规定B就是A的爹,因此去B找;但是B中没有test1,因此直接报错
class B:
def test(self):
print('from B')
class C(A,B):
def test1(self):
print('from C')
obj=C()
obj.test()
print(C.mro())
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
from A
Traceback (most recent call last):
File "C:/Users/baobao/PycharmProjects/untitled1/hello.py", line 15, in <module>
obj.test()
File "C:/Users/baobao/PycharmProjects/untitled1/hello.py", line 4, in test
super().test1()
AttributeError: 'super' object has no attribute 'test1'