zoukankan      html  css  js  c++  java
  • 【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

  • 相关阅读:
    成功率最高的发送邮件代码
    更改ReSharper的智能提示
    [转]SQL 2000 Insert返回自动编号id三种方法比较
    得到汉字的拼音首字母
    不能正确显示UltraWebGrid的解决方法.
    [转]asp.net使用json
    [转] 技术是一种加速器 但重要的不是技术
    [原]模仿Google首页的PNG动画效果
    一个通过DataSet操作XML的类
    C# partial 关键字详解
  • 原文地址:https://www.cnblogs.com/fcyworld/p/6240482.html
Copyright © 2011-2022 走看看