Python类变量初始化
我想把一些关于类的信息存储为类的(静态)变量。但是,我搞不清楚这些变量是怎么初始化的。这里有一个简单的例子:
class A(object):
clsVar = 'a'
@classmethod
def clsMeth(cls):
print 'changing clsVar'
cls.clsVar = 'b'
A.clsMeth()
# prints 'changing clsVar'
print A.clsVar # prints 'a'
A.clsVar = 'b'
print A.clsVar # prints 'b'
既然这个函数被调用了(因为打印语句有效),为什么类变量没有保持更改呢?如果我不想等到类定义完成后再做这些,难道就必须使用一个 metaclass 吗?
[具体来说,我想让 clsMeth
成为一个装饰器,并且让类变量成为一个包含所有被装饰函数的列表。我猜这不是实现这个目标的正确方法,所以我已经放弃了,但我还是很好奇。]
编辑:正如很多人指出的,上面的代码是无法运行的。我是在一个 IPython 会话中运行的,在那里调用 A.clsMeth()
会引用 A
的一个之前版本并执行。使用解释型语言就是有这样的风险。我最后选择了类似这样的方式:
outsideDict = {}
def outsideDec(func):
outsideDict[func.__name__] = func
class A(object):
@outsideDec
def someMethod(self):
print 'ID %s' % id(self)
def otherMethod(self):
print 'other'
print outsideDict
one, two = A(), A()
outsideDict['someMethod'](one)
outsideDict['someMethod'](two)
也许这应该是另一个问题,但当 outsideDec
被运行时,有没有办法知道它的参数属于哪个类?或者在 Python 中有没有更好的方法来进行这样的自省?我意识到我偏离了主题,所以我会接受下面的答案并做更多的研究。谢谢大家!
1 个回答
6
在定义 A
的时候,调用 A.clsMeth()
是不会执行的,因为那个时候 A
还不存在:
>>> class A(object):
... clsVar = 'a'
... @classmethod
... def clsMeth(cls):
... print 'changing clsVar'
... cls.clsVar = 'b'
... A.clsMeth()
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in A
NameError: name 'A' is not defined
如果 A
之前已经定义过,代码可能看起来能正常工作(比如你在 REPL 里测试的时候),但调用 A.clsMeth
实际上是针对旧的类进行的,而这个旧的类会被新的类覆盖。
不过,我们可以把这个调用放在定义之后,这样就能得到你想要的结果:
>>> class A(object):
... clsVar = 'a'
... @classmethod
... def clsMeth(cls):
... print 'changing clsVar'
... cls.clsVar = 'b'
...
>>> A.clsMeth()
changing clsVar
>>> A.clsVar
'b'
当然,正如 fabianhrj 提到的,你也可以把它放在构造函数里,但这样的话,直到你创建一个实例的时候,它才会被调用。