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)**)?**中的)。
发布于 2010-05-03 15:26:05
简短的回答:不,在Python2.x中无法用正确的父类的正确参数隐式调用正确的__init__。
顺便说一句,这里所示的代码是不正确的:如果使用super().__init__,那么您的层次结构中的所有类都必须在其__init__方法中具有相同的签名。否则,如果引入使用多重继承的新子类,代码就会停止工作。
有关此问题的更长描述(有图片),请参见http://fuhm.net/super-harmful/。
发布于 2010-03-01 10:32:09
也许你要找的是元类?
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的所有基类。
发布于 2010-04-30 08:24:05
您的代码与方法解析顺序无关。方法解析出现在多重继承的情况下,而不是您的示例。您的代码是错误的,因为您假设self.__class__实际上是定义方法的类,这是错误的:
>>> 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>
>>> 所以当你应该打电话:
super(B, self).__init__(1, b, c)你的确是在打电话:
# super(self.__class__, self).__init__(1, b, c)
super(C, self).__init__(1, b, c)编辑:尝试更好地回答问题。
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指纹:
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,以便您只需要访问该属性。
例如:
>>> 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
>>> https://stackoverflow.com/questions/2354769
复制相似问题