为什么超类属性在当前类的命名空间中不可用?

时间:2012-01-25 06:14:00

标签: python class namespaces python-3.x class-attributes

示例:

class A:
    a = 1

class B(A):
    b = 2
    y = b # works fine
    x = a # NameError: name 'a' is not defined
    x = A.a # works fine

z = B()
z.a # works fine
B.a # works fine

为什么不允许x = a?在每个其他上下文中(通过实例访问,通过子类名称访问)它工作正常;但不知何故,在课堂内部,它不起作用。

考虑到这种行为,我似乎无法实现一个类层次结构,其中每个类定义了一些额外的属性 - 因为我不能在子类中访问它们而不知道它们在层次结构中的确切位置。

这是我正在尝试(未成功)做的事情:

class X:
  accelerate = compose(f1, f2, f3) # f1, f2, f3 are functions

class Y(X):
  move = compose(f4, f5)
  stop = f6

class Z(Y):
  action = compose(accelerate, stop)

class U(Y):
  action = compose(move, stop)

这些类根本不会被初始化;我只是想用它们来创建一个功能层次结构。

2 个答案:

答案 0 :(得分:2)

类成员 definitions 不必以类名为前缀(因为它们在class块内),但是accesses会这样做(因为它不清楚)你想要访问的内容。)

您可以访问b,因为它已经在该代码块的本地范围内(它已在那里定义)。 a不是;它只在课程完全定义后出现。

为什么需要x = a?为什么要将一个成员变量的值基于另一个?如果你真的想要,你可以使用类的__init__函数来复制值(因为子类是在__init__运行的时间完全定义的。)

答案 1 :(得分:1)

Ben的答案很好地解释了发生了什么。

因为你在Python 3中工作,所以Python的元类中添加了一个功能,它允许你想要做的事情 - 一个类的本地字典可以更新(以非hacky方式,如显式调用解析类体之前的“locals()”。

所需要的只是在元类上使用__prepare__方法 - 它传递类名,它的基础作为元组,并且应该返回将用于解析元组的字典对象。身体类:

class MetaCompose(type):
    @staticmethod
    def __prepare__(name, bases):
        dct = {}
        for base in reversed(bases):
            dct.update(base.__dict__)
        return dct


class A:
    a = 1

class B(A, metaclass=MetaCompose):
    x = a


B.x

(参见http://docs.python.org/py3k/reference/datamodel.html#customizing-class-creation