# -*- encoding: utf-8 -*-
from pprint import pprint
'''
第25条: 用super初始化父类
关键:
1 初始化父类的方式
方式1: 在子类中调用父类的__init__方法,
样例:
ParentClass.__init__(self, value)
问题:
1) 多重继承会调用超类的__init__
2) 调用顺序不固定:
继承超类的顺序虽然变化,但如果初始化超类的顺序不变,结果不会随继承超类的变化而变化
3) 钻石继承问题:
假设子类有两个单独超类,每个超类继承自同一个公共基类,导致公共基类多次执行
__init__方法,产生意想不到的行为,每次调用最顶端的父类导致之前计算的值失效,
再次恢复为初始值。
2 用super初始化父类
原因: super函数定义了方法解析顺序,解决超类初始化顺序。
原则: 深度优先,从左到右
语法: super(当前类名称, self).__init__(参数列表)
python3中可以用 __class__来代替当前类名称
3 super解析顺序
顺序: 深度优先,从左到右
举例:
class BaseClass(object):
def __init__(self, value):
self.value = value
class TimesFiveCorrect(BaseClass):
def __init__(self, value):
super(TimesFiveCorrect, self).__init__(value)
self.value *= 5
class PlusTwoCorrect(BaseClass):
def __init__(self, value):
super(PlusTwoCorrect, self).__init__(value)
self.value += 2
class FourthWay(TimesFiveCorrect, PlusTwoCorrect):
def __init__(self, value):
super(FourthWay, self).__init__(value)
从左到右的继承超类的顺序是:
FourthWay->TimesFiveCorrect->PlusTwoCorrect->BaseClass
7*5=35<------5+2=7<------5<------传入5
那么传入5后,BaseClass先接收到5,接下来下一个是+2变为7.最后乘以5得到35
4 总结
python需要用标准方法解析顺序解决超类初始化和钻石继承问题
应该用内置的super函数来初始化父类。
参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''
class BaseClass(object):
def __init__(self, value):
self.value = value
class MultiplyTwo(object):
def __init__(self):
# self.value = value
self.value *= 2
class PlusFive(object):
def __init__(self):
# self.value = value
self.value += 5
class OneWay(BaseClass, MultiplyTwo, PlusFive):
def __init__(self, value):
BaseClass.__init__(self, value)
MultiplyTwo.__init__(self)
PlusFive.__init__(self)
class TwoWay(BaseClass, PlusFive, MultiplyTwo):
def __init__(self, value):
BaseClass.__init__(self, value)
MultiplyTwo.__init__(self)
PlusFive.__init__(self)
class TimesFive(BaseClass):
def __init__(self, value):
BaseClass.__init__(self, value)
self.value *= 5
class PlusTwo(BaseClass):
def __init__(self, value):
BaseClass.__init__(self, value)
self.value += 2
class ThirdWay(TimesFive, PlusTwo):
def __init__(self, value):
TimesFive.__init__(self, value)
PlusTwo.__init__(self, value)
class TimesFiveCorrect(BaseClass):
def __init__(self, value):
super(TimesFiveCorrect, self).__init__(value)
self.value *= 5
class PlusTwoCorrect(BaseClass):
def __init__(self, value):
super(PlusTwoCorrect, self).__init__(value)
self.value += 2
class FourthWay(TimesFiveCorrect, PlusTwoCorrect):
def __init__(self, value):
super(FourthWay, self).__init__(value)
def process():
result = OneWay(5)
print "First order is (5 * 2) + 5 = {value}".format(
value=result.value
)
result = TwoWay(5)
print "Two order is (5 * 2) + 5 = {value}".format(
value=result.value
)
result = ThirdWay(5)
print "Should be (5 * 5) + 2 = 27, but is: {value}".format(
value=result.value
)
result = FourthWay(5)
print "Should be 5 * (5 + 2) = 35, still is: {value}".format(
value=result.value
)
pprint(FourthWay.mro())
if __name__ == "__main__":
process()