给定
class A:
x = 'Ac'
def f(self):
return self.x
class B(A):
x = 'Bc'
def f(self):
return self.x
class C(A):
x = 'Cc'
def f(self):
return self.x
class D(B, C):
x = 'Dc'
def __init__(self):
self.x = 'Di'
def f(self):
return self.x
d = D()
d.x
的名称解析顺序是什么?例如Di, Dc, Bc, Cc, Ac
super(D, d).x
的名称解析顺序是什么?super(D, d).f()
中self.x
的nro是多少?它与d.f()
相同吗?D.x
的nro是多少?如果我分配给
d.x
,而Di
不在那里,它会去哪里?例如Di
或Dc
如果我分配给
D.x
,而Dc
不在那里,它会去哪里?如果我分配给
super(D, d).x
,而Bc
不在那里,它会去哪里?例如Di
或Dc
或Bc
如果您的对象是新样式对象(继承自object
),您可以使用__mro__
属性或mro
方法打印出方法解析顺序来获得答案。
将A类修改为如下所示:
class A(object):
...
然后你可以打印出每个类的方法分辨率顺序:
>>> A.__mro__
(<class 'junk.A'>, <type 'object'>)
>>> B.__mro__
(<class 'junk.B'>, <class 'junk.A'>, <type 'object'>)
>>> C.__mro__
(<class 'junk.C'>, <class 'junk.A'>, <type 'object'>)
>>> D.__mro__
(<class 'junk.D'>, <class 'junk.B'>, <class 'junk.C'>, <class 'junk.A'>, <type 'object'>)
新样式Python类中的stackoverflow问题方法解析顺序(MRO)提供了一些有用的信息。
首先,如果在每个点分配不同的值,而不是在所有地方都分配None,这会让事情变得容易得多。但我会尽力按要求回答你的问题。
首先要注意的是,d
实例实际上只有x
的1个副本,而不是4个。你可以很容易地测试这个:
>>> d.x = 3
>>> B.f(d)
3
在像C++这样的语言中,输出应该是None,因为D有单独的B::x、C::x和D::x数据成员。(我在这里假装A不存在,因为它使讨论变得更加复杂,而且实际上与问题无关。)
或者,更容易:
>>> dir(d)
['__doc__', '__init__', '__module__', 'f', 'x']
这就是所有的成员;你已经给同一个自己分配了四次。
另一方面,每个类都有自己的副本。如果没有实例变量,则按与mro相同的顺序搜索这些变量。你可以再次轻松测试:
>>> del d.x
>>> B.x = 4
>>> C.x = 5
>>> D.x = 6
>>> d.f()
6
>>> C.f(d)
6
>>> del D.x
>>> d.f()
4
至于设置,这很容易:设置d.x
总是设置实例变量(记住,只有1个,而不是4个),或者在不存在实例变量的情况下创建实例变量。同时,设置D.x
或B.x
为该类设置或创建类变量。因此,继承层次结构是无关紧要的。