Effective Python 读书笔记: 第25条: 用super初始化父类

# -*- 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() 

猜你喜欢

转载自blog.csdn.net/qingyuanluofeng/article/details/88879374