简体   繁体   English

Python类变量初始化

[英]Python Class Variable Initialization

I'd like to store some information about a class as class (static) variables. 我想将类的一些信息存储为类(静态)变量。 However, I can't figure out how these things get initialized. 但是,我无法弄清楚这些东西是如何初始化的。 Here is a basic, dumb example: 这是一个基本的,愚蠢的例子:

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'

Since the function got called (as the print statement worked), why didn't the class variable stay changed? 由于调用了函数(因为print语句有效),为什么类变量不会保持更改? Do I have to use a metaclass if I don't want to do it after the class definition completes? 如果在类定义完成后我不想这样做,我是否必须使用元类?

[Specifically, I want clsMeth to be a decorator and have the class variable be a list of all the functions that were so decorated. [具体来说,我希望clsMeth是一个装饰器,并让类变量成为所有装饰的函数的列表。 I'm guessing this isn't the right way to go about accomplishing that, so I've moved on, but I'm still curious.] 我猜这不是完成这个的正确方法,所以我继续前进,但我仍然很好奇。

EDIT: As numerous people have pointed out, the code above won't run. 编辑:正如许多人所指出的,上面的代码将无法运行。 I was running it in an IPython session where the call to A.clsMeth() would refer to a previous version of A and run. 我在一个IPython会话中运行它,其中对A.clsMeth()的调用将引用先前版本的A并运行。 Such are the risks of using an interpreted language, I guess. 我想这就是使用解释性语言的风险。 I ended up going with something like this: 我结束了这样的事情:

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)

Perhaps this should be another question, but when outsideDec gets run, is there a way to tell what class it's argument is a member of? 也许这应该是另一个问题,但是当outsideDec运行时,有没有办法告诉它的参数是什么类? Or is there a better way of doing introspection like this in Python? 或者,有没有更好的方法在Python中进行这样的内省? I recognize I'm veering off course here so I'll accept the answer below and do more research. 我知道我在这里偏离正轨,所以我会接受下面的答案并做更多的研究。 Thanks everyone! 感谢大家!

The call to A.clsMeth() in the definition of A will not run, as A does not exist at that point: 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

The code may have seemed to work if A had been defined previously (eg, if you were testing it out in the REPL), but the call to A.clsMeth would have been called on the old class, which would be shadowed by the new one. 如果之前已经定义了A (例如,如果你在REPL中测试它),那么代码可能似乎有效,但是对旧的类调用了对A.clsMeth的调用,这将被新的类所影响。一。

However, we can definitely put that call after the definition and get the result you want: 但是,我们绝对可以在定义之后调用该调用并获得您想要的结果:

>>> class A(object):
...     clsVar = 'a'
...     @classmethod
...     def clsMeth(cls):
...         print 'changing clsVar'
...         cls.clsVar = 'b'
...
>>> A.clsMeth()
changing clsVar
>>> A.clsVar
'b'

Of course, as fabianhrj noted, you can put it in the constructor as well, but it won't be called until you create an instance. 当然,正如fabianhrj所指出的,你也可以将它放在构造函数中,但是在创建实例之前不会调用它。

You need to put all statement in a function for them to work. 您需要将所有语句放在函数中才能使它们起作用。 I recommend that if you want to run something when the object is created just put it in the constructor. 我建议如果你想在创建对象时运行一些东西,只需将它放在构造函数中。

class A:
    def clsMeth(self):
        print("Changing clsVar")
        self.clsVar = 'b'
    def __init__(self):
        self.clsMeth()
    clsVar = 'a'

There we are. 我们在那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM