首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >隐式调用父类初始化程序

隐式调用父类初始化程序
EN

Stack Overflow用户
提问于 2010-03-01 09:17:57
回答 4查看 4.3K关注 0票数 7
代码语言:javascript
复制
class A(object):
    def __init__(self, a, b, c):
        #super(A, self).__init__()
        super(self.__class__, self).__init__()


class B(A):
    def __init__(self, b, c):
        print super(B, self)
        print super(self.__class__, self)
        #super(B, self).__init__(1, b, c)
        super(self.__class__, self).__init__(1, b, c)

class C(B):
    def __init__(self, c):
        #super(C, self).__init__(2, c)
        super(self.__class__, self).__init__(2, c)
C(3)

在上面的代码中,注释掉的__init__调用似乎是进行超类初始化的普遍接受的“智能”方法。但是,如果类层次结构可能发生变化,我一直使用未注释的表单,直到最近。

在上述层次结构中对B的超级构造函数的调用中,再次调用B.__init__时,self.__class__实际上是C,而不是我一直假设的B

在Python-2.x中有某种方式可以在调用超级构造函数时维护正确的MRO (有关以正确的顺序初始化所有父类),而不是命名当前类(在B super(B, self).__init__(1, b, c)**)?**中的)。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-05-03 15:26:05

简短的回答:不,在Python2.x中无法用正确的父类的正确参数隐式调用正确的__init__

顺便说一句,这里所示的代码是不正确的:如果使用super().__init__,那么您的层次结构中的所有类都必须在其__init__方法中具有相同的签名。否则,如果引入使用多重继承的新子类,代码就会停止工作。

有关此问题的更长描述(有图片),请参见http://fuhm.net/super-harmful/

票数 3
EN

Stack Overflow用户

发布于 2010-03-01 10:32:09

也许你要找的是元类?

代码语言:javascript
复制
class metawrap(type):
    def __new__(mcs,name, bases, dict):
        dict['bases'] = bases
        return type.__new__(mcs,name,bases,dict)

class A(object):
    def __init__(self):
        pass
    def test(self):
        print "I am class A"

class B(A):
    __metaclass__ = metawrap
    def __init__(self):
        pass
    def test(self):
        par = super(self.bases[0],self)
        par.__thisclass__.test(self)
foo = B()
foo.test()

打印“我是A类”

元类所做的是覆盖B类的初始创建(而不是对象),并确保每个B对象的内置字典现在包含一个基数组,您可以在其中找到B的所有基类。

票数 1
EN

Stack Overflow用户

发布于 2010-04-30 08:24:05

您的代码与方法解析顺序无关。方法解析出现在多重继承的情况下,而不是您的示例。您的代码是错误的,因为您假设self.__class__实际上是定义方法的类,这是错误的:

代码语言:javascript
复制
>>> class A(object):
...     def __init__(self):
...         print self.__class__
... 
>>> 
>>> class B(A):
...     def __init__(self):
...         A.__init__(self)
... 
>>> B()
<class '__main__.B'>
<__main__.B object at 0x1bcfed0>
>>> A()
<class '__main__.A'>
<__main__.A object at 0x1bcff90>
>>> 

所以当你应该打电话:

代码语言:javascript
复制
super(B, self).__init__(1, b, c)

你的确是在打电话:

代码语言:javascript
复制
# super(self.__class__, self).__init__(1, b, c)
super(C, self).__init__(1, b, c)

编辑:尝试更好地回答问题。

代码语言:javascript
复制
class A(object):
    def __init__(self, a):
        for cls in self.__class__.mro():
            if cls is not object:
                cls._init(self, a)
    def _init(self, a):
        print 'A._init'
        self.a = a

class B(A):
    def _init(self, a):
        print 'B._init'

class C(A):
    def _init(self, a):
        print 'C._init'

class D(B, C):
    def _init(self, a):
        print 'D._init'


d = D(3)
print d.a

指纹:

代码语言:javascript
复制
D._init
B._init
C._init
A._init
3

(模板模式的修改版本)。

现在,父母的方法实际上被称为隐式方法,但我不得不同意python的观点,即显式优于隐式,因为代码的可读性较低,增益也很差。但是请注意,所有的_init方法都有相同的参数,您不能完全忘记父母,我不建议这样做。

对于单个继承,更好的方法是显式调用父方法,而不调用super。这样做,您不需要命名当前的类,但您仍然必须关心谁是父类。

好的读物是:how-does-pythons-super-do-the-right-thing和问题中所建议的链接,以及特殊的Python的Super很棒,但是你不能用它

如果层次结构可能发生变化,则是不良设计的症状,并且对使用该代码的所有部分都有影响,因此不应鼓励。

编辑2

我想到了另一个例子,但它使用元类。Urwid库使用元类用于在类中存储属性__super,以便您只需要访问该属性。

例如:

代码语言:javascript
复制
>>> class MetaSuper(type):
...     """adding .__super"""
...     def __init__(cls, name, bases, d):
...         super(MetaSuper, cls).__init__(name, bases, d)
...         if hasattr(cls, "_%s__super" % name):
...             raise AttributeError, "Class has same name as one of its super classes"
...         setattr(cls, "_%s__super" % name, super(cls))
... 
>>> class A:
...  __metaclass__ = MetaSuper
...  def __init__(self, a):
...   self.a = a
...   print 'A.__init__'
... 
>>> class B(A):
...  def __init__(self, a):
...   print 'B.__init__'
...   self.__super.__init__(a)
... 
>>> b = B(42)
B.__init__
A.__init__
>>> b.a
42
>>> 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2354769

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档