【问题标题】:Python Class Variable InitializationPython 类变量初始化
【发布时间】:2012-01-20 12:58:42
【问题描述】:

我想将一些关于类的信息存储为类(静态)变量。但是,我无法弄清楚这些东西是如何被初始化的。这是一个基本的,愚蠢的例子:

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 成为一个装饰器,并让类变量成为所有被如此装饰的函数的列表。我猜这不是实现这一目标的正确方法,所以我继续前进,但我仍然很好奇。]

编辑:正如许多人指出的那样,上面的代码不会运行。我在 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 中进行这样的内省?我知道我在这里偏离了方向,所以我会接受下面的答案并做更多的研究。谢谢大家!

【问题讨论】:

  • 调用A.clsMeth 时出现错误,因为A 未定义。也许您正在使用解释器并且您有一个旧的 A 定义?
  • 如何运行此示例?这不起作用,因为语法不正确。 A.clsMth() 不能像这样放在类定义中。
  • @gecco:当然可以;语法很好。正如 jcollado 所提到的,它会因运行时错误而失败,因为在调用 A.clsMeth() 时尚未分配给 A,但您可以这样做。

标签: python initialization class-variables


【解决方案1】:

A 的定义中对@9​​87654321@ 的调用将不会运行,因为此时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 所说,您也可以将它放在构造函数中,但在创建实例之前不会调用它。

【讨论】:

    猜你喜欢
    • 2015-08-24
    • 2016-11-03
    • 2020-03-18
    • 1970-01-01
    • 2015-04-22
    • 2012-07-04
    • 2016-09-07
    • 2022-01-13
    • 2021-08-12
    相关资源
    最近更新 更多