[英]How do you mix old-style and new-style Python classes?
我已经看过关于这个主题的几个问题,但我还没有找到明确的答案。
我想知道在新的Python代码库中使用旧式类的正确方法。 比方说,我有两个固定的类, A和B. 如果我想要子类A和B ,并转换为新式类( A2和B2 ),这是有效的。 但是,如果我想从A2和B2创建新的C类,则会出现问题。
因此,是否可以继续使用此方法,或者如果任何基类被定义为旧式,那么所有类都必须符合旧式吗?
请参阅示例代码以获得说明:
class A:
def __init__(self):
print 'class A'
class B:
def __init__(self):
print 'class B'
class A2(A,object):
def __init__(self):
super(A2, self).__init__()
print 'class A2'
class B2(B,object):
def __init__(self):
super(B2, self).__init__()
print 'class B2'
class C(A2, B2):
def __init__(self):
super(C,self).__init__()
print 'class C'
A2()
print '---'
B2()
print '---'
C()
这段代码的输出:
class A
class A2
---
class B
class B2
---
class A
class A2
class C
正如您所看到的,问题是在调用C()
,类B2从未初始化。
更新 - 新样式类示例
我想还不清楚使用super
时正确的初始化序列应该是什么。 这是一个工作示例,其中对super的调用会初始化所有基类,而不仅仅是它找到的第一个基类。
class A(object):
def __init__(self):
super(A, self).__init__()
print 'class A'
class B(object):
def __init__(self):
super(B, self).__init__()
print 'class B'
class A2(A):
def __init__(self):
super(A2, self).__init__()
print 'class A2'
class B2(B):
def __init__(self):
super(B2, self).__init__()
print 'class B2'
class C(A2, B2):
def __init__(self):
super(C, self).__init__()
print 'class C'
C()
并产生输出:
class B
class B2
class A
class A2
class C
这不是混合新旧类型的问题。 super()不调用所有基类函数,它根据方法解析顺序调用它找到的第一个函数。 在这种情况下,A2反过来调用A.
如果要同时调用它们,请明确地执行此操作:
class C(A2, B2):
def __init__(self):
A2.__init__(self)
B2.__init__(self)
print 'class C'
那应该解决它。
更新:
你所指的钻石继承问题是钻石继承情况下要调用哪个类的问题,如下所示:
class A:
def method1(self):
print 'class A'
def method2(self):
print 'class A'
class B(A):
def method1(self):
print 'class B'
class C(A):
def method1(self):
print 'class C'
def method2(self):
print 'class C'
class D(B, C):
pass
现在测试一下:
>>> D().method1()
'class B'
这是对的。 它调用了第一类的实现。 但是,让我们尝试使用method2:
>>> D().method2()
'class A'
Oups,错了! 它应该在这里调用类C.method2(),因为即使类B不重写method2,类C也可以。 现在让A类成为一个新类:
class A(object):
def method1(self):
print 'class A'
然后再试一次:
>>> D().method1()
'class B'
>>> D().method2()
'class C'
嘿presto,它的工作原理。 这是新旧类的方法解析顺序差异,这有时会使它们混淆。
注意B和C都不会被调用。 即使我们称之为超级也是如此。
class D(B, C):
def method1(self):
super(D, self).method1()
def method2(self):
super(D, self).method2()
>>> D().method1()
'class B'
>>> D().method2()
'class C'
如果你想同时调用B和C,你必须明确地调用它们。
现在,如果你破坏钻石,就像在你的例子中有单独的基类一样,结果是不同的:
class A1(object):
def method1(self):
print 'class A1'
def method2(self):
print 'class A1'
class A2(object):
def method1(self):
print 'class A2'
def method2(self):
print 'class A2'
class B(A1):
def method1(self):
print 'class B'
class C(A2):
def method1(self):
print 'class C'
def method2(self):
print 'class C'
class D(B, C):
def method1(self):
super(D, self).method1()
def method2(self):
super(D, self).method2()
>>> D().method1()
'class B'
>>> D().method2()
'class A1'
这也是每个设计。 仍然无法调用两个基类。 如果你想要这样做,你仍然必须明确地调用它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.