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

Python 如何引用基类';派生类中的属性?,python,Python,我可以这样做: 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) 不,我不能: 抛出以下错误: Traceback (most recent call last): File "./prog.py"

我可以这样做:

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)
不,我不能:

抛出以下错误:

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
回溯(最近一次呼叫最后一次):
文件“/prog.py”,第5行,在
Blah2中第6行的文件“/prog.py”
NameError:未定义名称“atttr”

为什么不工作以及如何使其工作?

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

这在本节中有记录

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


您的问题是这样解决的:

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
它打印1,因为在上面的第二行之后,现在有一个
c
属性
a
和一个
c
属性
a
,它们是两个不同的对象:

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

如果希望
c.a
不重写
c.a
,则需要了解属性和描述符。也许开始吧

您可能应该从创建这些类的实例开始,而不是访问这些类本身的属性。为什么需要这样做?您知道
Blah2
Blah1
是类,不是实例,是吗?实例继承其父字段,而不是类
>>> vars(c)
{'a': 2}
>>> vars(C)
{'a': 1}