【问题标题】:How do I initialize all inherited classes in python3.2?python3.2中如何初始化所有继承的类?
【发布时间】:2014-10-28 21:56:52
【问题描述】:

我正在使用 python3.2 并且我有一个继承两个类的类。子类的子类__init__ 函数具有不同的签名。简而言之,是否可以创建一个调用每个子类的__init__ 的Parent 对象?

背景

假设我有以下python3.2代码

class A(object):
    def __init__(self, name):
        self.ver = "the ver"
        print("A::__init__ .... name = %s" % name)

class B(object):
    def __init__(self,):
        self.name = "the name"
        print("B::__init__")
 
    def foo(self,):
        print("B::foo.   The name is >>%s<<" % self.name)

class C(B,A):
    def  __init__(self,):
        print("C::__init__")
        super(B, self).__init__()
        super(A, self).__init__('waaa') 

我可以创建AB 的实例

>>> a = A('myplace')
A::__init__ .... name = myplace
>>> b = B()
B::__init__

但是创建C 的实例失败。

>>> c = C()
C::__init__
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 4, in __init__
TypeError: __init__() takes exactly 2 arguments (1 given)

如果我将C__init__修改为

class C(B,A):
    def  __init__(self,):
      print("C::__init__")
      super(B, self).__init__('another')
      super(A, self).__init__('waaa') 

我在创建C 的实例时得到以下信息

>>> C()
C::__init__
A::__init__ .... name = another
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 5, in __init__
TypeError: object.__init__() takes no parameters
>>> 

我的问题

我阅读了super()的文档,不清楚是否可以调用每个子类的__init__

看来super(B, self)__init__('another')实际上是在调用A类的__init__,而super(A, self).__init__('waaa')是在调用B类的__init__

  1. 为什么super() 不尊重它的type 参数?
  2. 如何创建一个对象C,它同时具有AB 的所有类属性和方法?

【问题讨论】:

  • super重点就是你调用一次,所有继承的功能(包括多重继承)都处理好了。这确实意味着调用签名必须匹配(或使用*args**kwargs 来处理差异)。

标签: python oop python-3.x super


【解决方案1】:

您错误地使用了super();它并不是要显式调用特定的超级方法,而是要动态地在继承图中搜索下一个方法。 super() 使用类型查找开始搜索的位置,跳过传入的类型。

在这种情况下,你可以直接调用父级__init__

class C(B,A):
    def  __init__(self,):
      print("C::__init__")
      B.__init__(self)
      A.__init__(self, 'waaa') 

因为你的__init__ 方法有特定的签名,你不能只使用super();您的 __init__ 方法需要适合一个签名(可能是一个接受任意参数并忽略不需要的参数)。

明确地说,super() 的第一个参数告诉它在搜索请求的方法时要跳过什么类型,这就是为什么您通常传入 current类。

【讨论】:

    【解决方案2】:

    为什么super() 不尊重它的type 参数?

    因为super() 不使用type 参数作为要使用的类型。相反,根据MRO,它使用它来确定要使用的 next 类型。这就是为什么您将 current 类型传递给它的原因。

    如何创建一个对象 C,它同时具有 A 和 B 的所有类属性和方法?

    AB 也正确使用super()。是的,它会使向构造函数传递参数变得非常困难。不,除了“构造函数没有不同的签名”之外没有其他好的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 2012-02-18
      相关资源
      最近更新 更多