简体   繁体   English

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

[英]How to reference a base class' attribute in derived class?

I can do this: 我可以做这个:

class Blah2:
    atttr = 5
    aa = atttr


ob = Blah2
print(ob.aa)

http://ideone.com/pKxMc2 http://ideone.com/pKxMc2

So I assumed I could as well do this: 所以我假设我也可以这样做:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = atttr


ob = Blah2
print(ob.aa)

Nope I can't: http://ideone.com/6HS1MO 不,我不能: http//ideone.com/6HS1MO

SPits out the following error: 发出以下错误:

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

Why doesn't this work and how to make it working? 为什么这不起作用以及如何使其工作?

The class block scope only exists temporarily during class definition. 类块作用域仅在类定义期间临时存在。 After class definition, you would have to access that attribute via the class object, ie Blah1.atttr . 在类定义之后,您必须通过类对象访问该属性,即Blah1.atttr

This is documented under the execution model section. 这在执行模型部分中有记录。

Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. exec()和eval()的类定义块和参数在名称解析的上下文中是特殊的。 A class definition is an executable statement that may use and define names. 类定义是可以使用和定义名称的可执行语句。 These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. 这些引用遵循名称解析的常规规则,但在全局命名空间中查找未绑定的局部变量。 The namespace of the class definition becomes the attribute dictionary of the class. 类定义的名称空间成为类的属性字典。 The scope of names defined in a class block is limited to the class block ; 类块中定义的名称范围仅限于类块 ; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope. 它没有扩展到方法的代码块 - 这包括了解和生成器表达式,因为它们是使用函数作用域实现的。

Your problem is fixed like this: 您的问题修复如下:

class Blah1:
    atttr = 5


class Blah2(Blah1):
    aa = BLah1.atttr

However, as pointed out in the comments, this is a weird thing to do. 但是,正如评论中指出的那样,这是一件很奇怪的事情。 Now you have this: 现在你有了这个:

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

EDIT: As stated in wim's answer, the cause of this is how scoping works inside of a class definition. 编辑:正如在wim的回答中所述,其原因在于如何在类定义中使用作用域。 When you do this: 当你这样做:

class C():
    a = 1

It is pretty much equivalent to this: 它几乎相当于:

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

As you can see, in order to access that a anywhere outside of the class definition body, you have to refer to it using the class (or an instance of the class): Ca or c().a . 正如你所看到的,为了访问a类定义体以外的任何位置,你必须使用类(或类的实例)来引用它: Cac().a But note this "gotcha": 但请注意这个“问题”:

class C():
    a = 1

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

It prints 1 because after the second line above, there is now both a c attribute a and a C attribute a , and they are two different objects: 它打印1因为在上面的第二行之后,现在既有c属性a又有C属性a ,它们是两个不同的对象:

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

If you want ca to not override Ca , you need to learn about properties and descriptors. 如果您希望ca不覆盖Ca ,则需要了解属性和描述符。 Maybe start here . 也许从这里开始。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM