我想将有关类的一些信息存储为类(静态)变量。但是,我不知道如何初始化这些东西。这是一个简单的基本示例:

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'

由于调用了该函数(当print语句起作用时),为什么类变量保持不变?如果在类定义完成后不想这样做,是否必须使用元类?

[具体来说,我希望clsMeth成为装饰器,并让class变量成为所有经过如此装饰的函数的列表。我猜想这不是实现此目标的正确方法,所以我继续前进,但我仍然很好奇。

编辑:正如许多人指出的那样,上面的代码将无法运行。我在IPython session 中运行它,对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中有更好的自省(introspection)方法?我知道我在这里偏离方向,所以我将接受下面的答案并做更多的研究。谢谢大家!

最佳答案

A.clsMeth()定义中对A的调用将不会运行,因为此时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指出的那样,您也可以将其放在构造函数中,但是只有在创建实例后才可以调用它。

10-06 15:50