• 【Python】使用super初始化超类


    初始化超类的传统方式,在子类的实例中调用超类的__init__()方法。

    但是传统的方法有两个问题,比如:

    问题1:

     1 class MyBaseClass:
     2     def __init__(self, value):
     3         self.value = value
     4 
     5 
     6 class TimesTwo:
     7     def __init__(self):
     8         self.value *= 2
     9 
    10 
    11 class PlusFive:
    12     def __init__(self):
    13         self.value += 5
    14 
    15 
    16 class OneWay(MyBaseClass, TimesTwo, PlusFive):
    17     def __init__(self,value):
    18         MyBaseClass.__init__(self, value)
    19         TimesTwo.__init__(self)
    20         PlusFive.__init__(self)
    21 
    22 
    23 class AnotherWay(MyBaseClass,  PlusFive, TimesTwo):
    24     def __init__(self,value):
    25         MyBaseClass.__init__(self, value)
    26         TimesTwo.__init__(self)
    27         PlusFive.__init__(self)
    28 
    29 foo = OneWay(5)
    30 print('OneWay (5*2)+5=', foo.value)
    31 foo = AnotherWay(5)
    32 print('AnotherWay:', foo.value)

    结果为:

    从结果可以看出,即使改变了子类的继承顺序,调用的顺序并没有改变。

    问题2:

    如果子类继承自两个单独的超类,而那两个超类又继承自同一个公共基类,那么就构成了钻石型继承。

    这种继承会使钻石顶端的公共基类多次执行__init__()方法,从而产生意外。

    比如:

     1 class MyBaseClass:
     2     def __init__(self, value):
     3         self.value = value
     4 
     5 
     6 class TimesFive(MyBaseClass):
     7     def __init__(self, value):
     8         MyBaseClass.__init__(self, value)
     9         self.value *= 2
    10 
    11 
    12 class PlusTwo(MyBaseClass):
    13     def __init__(self, value):
    14         MyBaseClass.__init__(self, value)
    15         self.value += 2
    16 
    17 
    18 class ThisWay(TimesFive, PlusTwo):
    19     def __init__(self, value):
    20         TimesFive.__init__(self, value)
    21         PlusTwo.__init__(self, value)
    22 
    23 
    24 
    25 foo = ThisWay(5)
    26 print('Should be (5*5)+2 but is ', foo.value)

    在调用PlusTwo.__init__()时候,又一次调用MyBaseClass.__init__()又一次把value变为5

    以上两种问题都可以使用super解决,方法解析顺序mro(method resolution order),以标准的流程安排超类之间的初始化顺序。

    比如这次用super初始化超类

     1 class MyBaseClass:
     2     def __init__(self, value):
     3         self.value = value
     4 
     5 
     6 class TimesFive(MyBaseClass):
     7     def __init__(self, value):
     8         super(TimesFive, self).__init__(value)
     9         self.value *= 5
    10 
    11 
    12 class PlusTwo(MyBaseClass):
    13     def __init__(self, value):
    14         super(PlusTwo, self).__init__(value)
    15         self.value += 2
    16 
    17 
    18 class GoodWay(TimesFive, PlusTwo):
    19     def __init__(self, value):
    20         super(GoodWay, self).__init__(value)
    21 
    22 
    23 foo = GoodWay(5)
    24 print('Should be 5*(5+2) and is ', foo.value)

    并且可以使用

    print(GoodWay.mro())

    来查看初始化顺序:

    参考资料:Effective Python

  • 相关阅读:
    Android 6.0权限
    从最简单的HelloWorld理解MVP模式
    DataSet、DataTable和DataGridView知识备忘
    Windows 窗体启动和关闭的事件顺序
    VB二进制文件读写
    C#操作符的重载
    虚方法(virtual)和抽象方法(abstract)的区别
    我的前端页面开发js简易有效环境
    css properties
    css属性值语法解读
  • 原文地址:https://www.cnblogs.com/fcyworld/p/6240482.html
Copyright © 2020-2023  润新知