派生
【一】概要
- "派生"(Derivation)是指在面向对象编程中,通过创建新的类,基于已有的类(通常称为父类或基类)来构建新的类,以获取和扩展父类的属性和方法。在这个过程中,新创建的类称为子类或派生类。
- 通俗来讲,派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法
【二】常用方法
【1】指名道姓
class 父类():
def __init__(self,参数1,参数2):
self.参数1 = 参数1
self.参数2 = 参数2
class 派生类(父类):
'''此处派生是为了,继承父类的初始化属性,并初始化自己的属性'''
def __init__(self,参数1,参数2,派生类自己的参数):
# 不依赖于继承,不是父类也可以重写
父类.__init__(self,参数1,参数2)
# 需要将self传入
【2】super()
class 父类():
def __init__(self,参数1,参数2):
self.参数1 = 参数1
self.参数2 = 参数2
class 派生类(父类):
'''此处派生是为了,继承父类的初始化属性,并初始化自己的属性'''
def __init__(self,参数1,参数2,派生类自己的参数):
# 依赖于继承
# 使用super方法就可以默认向上查找父类中的属性并重写
super().__init__(参数1,参数2)
# 不需要传递self
【三】详解
【1】指名道姓
class Father(object):
def __init__(self,name,age):
self.name = name
self.age = age
self.father_run =self.run
def run(self):
print(f"Father.run")
class Son(Father):
def __init__(self,name,age,level):
'''指名道姓的声明'''
Father.__init__(self,name,age)
self.level = level
def run(self):
# 方法可能不太明显,因为可以解释为调用
Father.run(self)
print(f"Son.run")
s = Son('son',5,'son')
print(s.__dict__) # {'name': 'son', 'age': 5, 'run': <bound method Son.run of <__main__.Son object at 0x00000152873E3FA0>>, 'level': 'son'}
s.run() # 将会输出两条,而不是一条
# Father.run
# Son.run
【2】super()
class Father(object):
def __init__(self,name,age):
self.name = name
self.age = age
self.father_run =self.run
def run(self):
print(f"Father.run")
class Son(Father):
def __init__(self,name,age,level):
super().__init__(name,age)
self.level = level
def run(self):
# super会更直观一些
super().run()
print(f"Son.run")
s = Son('son',5,'son')
print(s.__dict__) # {'name': 'son', 'age': 5, 'run': <bound method Son.run of <__main__.Son object at 0x00000152873E3FA0>>, 'level': 'son'}
s.run() # 将会输出两条,而不是一条
# Father.run
# Son.run
class A:
def run(self):
super().run()
print("A.run")
class B:
def run(self):
print("B.run")
class C(A,B):
pass
c = C()
c.run()
# B.run
# A.run
【3】super()
与mro()
super()
用于以一种一致而可预测的方式调用父类的方法,它遵循方法解析顺序(MRO)以确定应该查找哪个类的方法。
'''引:c.test() 的结果是什么?报错还是输出内容'''
class A:
def test(self):
# super是向上继承,而A是新式类,默认继承object
super().test()
class B:
def test(self):
print('from B')
class C(A, B):
pass
c = C()
c.test()
class A:
def test(self):
super().test()
class B:
def test(self):
print('from B')
class C(A, B):
pass
c = C()
c.test() # from B
# super() MRO以确定应该查找哪个类的方法。
# mro() 可以用来查看属性查找顺序
print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
- 类
C
的 MRO 是由类定义中基类的顺序确定的。在这种情况下是C(A, B)
,所以 MRO 是[C, A, B]
。当你调用c.test()
时,它会在 MRO 列表中的第一个类中(C
)查找test
方法,如果找不到,它会移到下一个类(A
),以此类推。 - 因此,在类
A
的test
方法中,当你使用super().test()
时,它会在 MRO 中的下一个类中查找test
方法,也就是B
。这样,它确保了方法是从 MRO 中的下一个类中调用的,提供了一种一致而可预测的导航类层次结构的方式。