我可以这样做:
class Blah2:
atttr = 5
aa = atttr
ob = Blah2
print(ob.aa)
所以我认为我也可以这样做:
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
为什么这不起作用以及如何使其发挥作用?
答案 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.a
或c().a
。但请注意这个“问题”:
class C():
a = 1
c = C()
c.a = 2
print(C.a) # prints 1!!!
它打印1,因为在上面的第二行之后,现在有c
属性a
和C
属性a
,它们是两个不同的对象:
>>> vars(c)
{'a': 2}
>>> vars(C)
{'a': 1}
如果您希望c.a
不覆盖C.a
,则需要了解属性和描述符。也许开始here。