-4

给定

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()
  1. 什么是名称解析顺序d.x?例如Di, Dc, Bc, Cc, Ac

  2. 什么是名称解析顺序super(D, d).x

  3. nro 是什么self.x意思super(D, d).f()?和 for 一样d.f()吗?

  4. nro 是干什么用的D.x

  5. 如果我分配到d.x并且Di不在那里,它会去哪里?例如DiDc

  6. 如果我分配到D.x并且Dc不在那里,它会去哪里?

  7. 如果我分配到super(D, d).x并且Bc不在那里,它会去哪里?例如DiDcBc

4

2 回答 2

3

如果您的对象是新样式对象(继承自),您可以通过使用属性或方法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 问题Method Resolution Order (MRO)有一些有用的信息。

于 2012-09-20T20:32:09.600 回答
2

首先,如果您在每个点分配不同的值而不是到处都分配无,这将使事情变得容易得多。但我会尽力回答你的问题。

首先要注意的是,该d实例实际上只有 1 个副本x,而不是 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']

这就是所有的成员;您已分配给同一个 self.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.xB.x设置或创建该类的类变量。因此,继承层次结构无关紧要。

于 2012-09-20T21:18:32.607 回答