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

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

我有以下python片段:

1
2
3
4
5
6
7
8
9
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

我的问题是:从EDOCX1×1中打印EDCOX1 0内容的正确方法是什么?和/或重新分配它们从EDCOX1到2?


您面临的问题是,您不了解类声明的作用域是如何工作的。类声明在其自身的范围内执行。执行完成后,将创建一个新的类对象,并将获得的作用域作为其__dict__附加到该类。

注意:在方法范围内不搜索类范围!这意味着您必须在方法定义中引用类属性作为MyClass.attribute

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)

注:由于该类在执行其声明时不存在,因此不能在myClass声明的"顶层"中引用myClass

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

这样做的一个副作用是,以下代码:

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

生产:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

因为生成器表达式(和python3中的列表理解)实际上被视为具有自己范围的函数。由于没有从内部函数范围中搜索类范围,因此找不到x

您可以使用函数定义和默认值来绕过此问题:

1
2
3
4
5
6
7
8
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)))()

这通常不是问题,因为类定义很少包含方法定义和一些常量以外的任何内容。

关于类范围,已经有一些关于so的问题:

  • 类块中定义的名称范围没有扩展到方法的块。为什么会这样?
  • 范围界定规则的简短描述?
  • 嵌套类的作用域?
  • python类中的变量范围
  • 为什么静态绑定对于类和函数的工作方式不同?


self.var将:

  • self.__dict__中给予var如果存在
  • self.__class__.__dict__中给予var如果存在
  • AttributeError
  • 因此,如果您想访问静态变量挖掘继承,请使用此或EDCOX1 6。如果扩展EDCOX1(7),则子实例将访问子类中的静态变量。

    如果您想访问EDCOX1中7的静态变量,即使从子代调用,也可以使用EDCOX1(9)。

    至于重新分配它们,必须明确地在类对象上完成,或者赋值将只针对实例。


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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'