如何在Python类中引用静态属性?
我有以下这段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 个回答
在编程中,有时候我们需要在代码里做一些判断,看看某个条件是否成立。这就像在生活中,我们会根据一些情况来做决定。例如,如果外面下雨了,我们就会带上雨伞。
在代码里,我们可以使用“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'
self.var
的作用是:
- 如果在
self.__dict__
中找到了var
,就返回它。 - 如果在
self.__class__.__dict__
中找到了var
,也会返回它。 - 如果都没有找到,就会报
AttributeError
错误。
所以,如果你想访问静态变量,记得要考虑继承的关系,可以用 self
或者 self.__class__.var
。如果你扩展了 myClass
,那么子类的实例会访问子类中的静态变量。
如果你想在调用子类时仍然访问 myClass
中的静态变量,可以直接用 myClass.var
。
至于重新赋值静态变量,这个必须在类对象上明确进行,否则赋值只会作用于实例。
你遇到的问题是因为你不太明白类声明的作用域是怎么回事。类声明是在它自己的作用域内执行的。执行完成后,会创建一个新的类对象,并将这个作用域作为它的 __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 上已经有一些相关问题: