如何引用基类'派生类中的属性?

时间:2017-08-04 03:30:20

标签: python

我可以这样做:

class Blah2:
    atttr = 5
    aa = atttr


ob = Blah2
print(ob.aa)

http://ideone.com/pKxMc2

所以我认为我也可以这样做:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = atttr


ob = Blah2
print(ob.aa)

不,我不能:http://ideone.com/6HS1MO

发出以下错误:

Traceback (most recent call last):
  File "./prog.py", line 5, in <module>
  File "./prog.py", line 6, in Blah2
NameError: name 'atttr' is not defined

为什么这不起作用以及如何使其发挥作用?

2 个答案:

答案 0 :(得分:2)

类块范围仅在类定义期间临时存在。在类定义之后,您必须通过类对象访问该属性,即Blah1.atttr

这是在execution model部分记录的。

  

exec()和eval()的类定义块和参数在名称解析的上下文中是特殊的。类定义是可以使用和定义名称的可执行语句。这些引用遵循名称解析的常规规则,但在全局命名空间中查找未绑定的局部变量。类定义的名称空间成为类的属性字典。 类块中定义的名称范围仅限于类块;它没有扩展到方法的代码块 - 这包括了解和生成器表达式,因为它们是使用函数作用域实现的。

答案 1 :(得分:1)

您的问题已修复如下:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = BLah1.atttr

然而,正如评论中指出的那样,这是一件很奇怪的事情。现在你有了这个:

>>> ob = Blah2()
>>> assert ob.aa == ob.atttr
True

编辑:正如wim的回答所述,其原因在于如何在类定义中使用作用域。当你这样做时:

class C():
    a = 1

这几乎相当于:

C = type('C', (), {}) # <--- dynamic class creation function
C.a = 1

如您所见,为了在类定义主体之外的任何地方访问a,您必须使用类(或类的实例)来引用它:C.ac().a。但请注意这个“问题”:

class C():
    a = 1

c = C()
c.a = 2
print(C.a) #  prints 1!!!

它打印1,因为在上面的第二行之后,现在有c属性aC属性a,它们是两个不同的对象:

>>> vars(c)
{'a': 2}
>>> vars(C)
{'a': 1}

如果您希望c.a不覆盖C.a,则需要了解属性和描述符。也许开始here