简体   繁体   English

如何在Python中引用类中的静态属性?

[英]How to reference a static attribute from within a class in Python?

I have the following python snippet: 我有以下python片段:

class myClass:
    myVar = 'a'

    def __init__(self):
        self.myOtherVar = 'b'
        myVar = 'c'  # Gets assigned but only as a local variable.

    print myVar            # prints 'a' !
    print self.myOtherVar  # says 'self' not found

My question is this; 我的问题是这个; What's the proper way to print the contents of myVar from within myClass and/or re-assign them from init ? myClass打印myVar的内容和/或从init重新分配它们的正确方法是什么?

The problem you are facing is because you don't understand how the scoping of class declarations work. 您遇到的问题是因为您不了解类声明的范围如何工作。 A class declaration is executed in its own scope. 类声明在其自己的范围内执行 After the execution is completed a new class object is created and the obtained scope is attached to the class as its __dict__ . 执行完成后,将创建一个新的类对象,并将获得的作用域作为__dict__附加到类中。

Note : the class scope is not searched from within the methods scopes! 注意不在方法范围内搜索类范围! This means that you have to reference class attributes as MyClass.attribute when inside a method definition. 这意味着您必须方法定义中引用类属性作为MyClass.attribute

For example: 例如:

class MyClass:
    var = 1

    # we are executing this code as a single block
    # so you must reference the variable as is usual
    print(var)

    # default values are *not* inside the definition.
    # they are evaluated in the outer scope, so use plain "var" here
    def method(self, a_default=var):
        print(a_default)

    def other_method(self):

        # inside methods you are in a different scope
        print(MyClass.var)

        # equivalent *if* no "var" instance attributes exists
        print(self.var)

Note: since the class doesn't still exist when executing its declaration you cannot refer to MyClass at the "top level" of MyClass declaration: 注:由于执行其声明中,您不能引用到上课的时候不依然存在MyClass在“顶级” MyClass声明:

class MyClass:
    var = 1
    print(MyClass.var)   # error: MyClass still doesn't exist.

A side effect of this, is that the following code: 这个的副作用是,以下代码:

class MyClass:
    x = 1
    results = list(i+x for i in range(10))

Produces: 生产:

NameError                                 Traceback (most recent call last)
<ipython-input-6-f1d4417b2e52> in <module>()
----> 1 class MyClass:
      2     x = 1
      3     results = list(i+x for i in range(10))
      4 

<ipython-input-6-f1d4417b2e52> in MyClass()
      1 class MyClass:
      2     x = 1
----> 3     results = list(i+x for i in range(10))
      4 

<ipython-input-6-f1d4417b2e52> in <genexpr>(.0)
      1 class MyClass:
      2     x = 1
----> 3     results = list(i+x for i in range(10))
      4 

NameError: name 'x' is not defined

Because generator expressions (and list-comprehensions in python3) are, in fact, considered functions with their own scope. 因为生成器表达式(以及python3中的列表推导)实际上被认为是具有自己范围的函数。 Since the class scope isn't searched from inner function scopes the x cannot be found. 由于未从内部函数范围搜索类范围,因此无法找到x

You can word around this using a function definition and default values: 您可以使用函数定义和默认值来解决此问题:

class MyClass:
    x = 1
    def _make_results(x=x):
        return list(i+x for i in range(10))
    results = _make_results()
    del _make_results    # otherwise it would be added as a method.
    # or:
    results = (lambda x=x: list(i+x for i in range(10)))()

This isn't usually a problem since class definitions rarely contain anything other than method definitions and a few constants. 这通常不是问题,因为类定义很少包含除方法定义和一些常量之外的任何内容。


There are already a few questions on SO about class scopes: 关于课程范围的问题已经有几个问题了:

self.var will: self.var将:

  1. give var in self.__dict__ if present varself.__dict__如果存在
  2. give var in self.__class__.__dict__ if present varself.__class__.__dict__如果存在
  3. AttributeError

So use this or self.__class__.var if you want to access the static variable minding inheritance . 因此,如果要访问静态变量minding继承,请使用this或self.__class__.var If you extend myClass , the children instances will access the static variable in the child class. 如果扩展myClass ,子实例将访问子类中的静态变量。

If you want to access the static variable in myClass even when called from descendants, use myClass.var . 如果要在myClass访问静态变量,即使从后代调用,也可以使用myClass.var

As for reassigning them, this must be done explicitly on the class object, or the assignment will just target the instance. 至于重新分配它们,必须在类对象上显式完成,或者赋值只是以实例为目标。

class myClass:
    myVar = 'a'

    def __init__(self):
        self.myOtherVar = 'b'

    print myVar  # -> 'a'

    class EmptyClass: pass
    s = EmptyClass()
    __init__(s)

    myVar = s.myOtherVar
    print myVar  # -> 'b'

print myClass.myVar  # -> 'b'

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

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