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

1 投票
3 回答
4158 浏览
提问于 2025-04-18 11:41

我有以下这段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

我的问题是;在myClass里面,怎样才能正确地打印出myVar的内容,或者从init里面重新给它赋值呢?

3 个回答

-4

在编程中,有时候我们需要在代码里做一些判断,看看某个条件是否成立。这就像在生活中,我们会根据一些情况来做决定。例如,如果外面下雨了,我们就会带上雨伞。

在代码里,我们可以使用“if”语句来进行这样的判断。它的基本结构是这样的:如果某个条件为真,就执行某段代码;如果条件不成立,可以选择执行另一段代码。

举个简单的例子,假设我们想检查一个数字是否大于10。如果是,就打印“这个数字很大”;如果不是,就打印“这个数字不大”。这就是一个简单的条件判断。

通过这种方式,我们可以让程序根据不同的情况做出不同的反应,这样就能更灵活地处理各种问题。

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'
0

self.var 的作用是:

  1. 如果在 self.__dict__ 中找到了 var,就返回它。
  2. 如果在 self.__class__.__dict__ 中找到了 var,也会返回它。
  3. 如果都没有找到,就会报 AttributeError 错误。

所以,如果你想访问静态变量,记得要考虑继承的关系,可以用 self 或者 self.__class__.var。如果你扩展了 myClass,那么子类的实例会访问子类中的静态变量。

如果你想在调用子类时仍然访问 myClass 中的静态变量,可以直接用 myClass.var

至于重新赋值静态变量,这个必须在类对象上明确进行,否则赋值只会作用于实例。

9

你遇到的问题是因为你不太明白类声明的作用域是怎么回事。类声明是在它自己的作用域内执行的。执行完成后,会创建一个新的类对象,并将这个作用域作为它的 __dict__ 附加到类上。

注意:类的作用域在方法的作用域中是无法访问的!这意味着在方法定义内部,你需要用 MyClass.attribute 来引用类的属性。

举个例子:

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

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

这导致了一个副作用,就是以下代码:

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

产生了:

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 找不到。

你可以通过使用函数定义和默认值来解决这个问题:

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)))()

通常这不是个问题,因为类定义里很少有其他内容,通常只有方法定义和一些常量。


关于类作用域,StackOverflow 上已经有一些相关问题:

撰写回答