简体   繁体   English

python方法内的静态变量

[英]static variables inside a python method

In a Python method, I would like to have a local variable whose value persists between calls to the method. 在Python方法中,我想要一个局部变量,该局部变量的值在调用该方法之间保持不变。

This question shows how to declare such "static variables" (c++ terminology) inside functions. 这个问题说明了如何在函数内部声明这种“静态变量”(c ++术语)。 I tried to do the same in an instance method, and failed. 我尝试在实例方法中执行相同操作,但失败了。

Here's a working minimal example that reproduces the problem. 这是一个重现该问题的最小示例。 You can copy-paste it into an interpreter. 您可以将其复制粘贴到解释器中。

class SomeClass(object):
    def some_method(self):
        if not hasattr(SomeClass.some_method, 'some_static_var'):
            SomeClass.some_method.some_static_var = 1  # breaks here

        for i in range(3):
            print SomeClass.some_method.some_static_var
            SomeClass.some_method.some_static_var += 1

if __name__ == '__main__':
    some_instance = SomeClass()
    some_instance.some_method()

On the line labeled "# breaks here", I get: 在标有“#break here here”的行上,我得到:

AttributeError: 'instancemethod' object has no attribute 'some_static_var'

I realize there's an easy workaround, where I make some_static_var a member variable of SomeClass . 我意识到有一个简单的解决方法,可以将some_static_var SomeClass的成员变量。 However, the variable really has no use outside of the method, so I'd much prefer to keep it from cluttering up SomeClass ' namespace if I could. 但是,该变量实际上在方法之外没有任何用处,因此,如果可以的话,我更希望避免使该变量混乱SomeClass '命名空间。

In python 2, you have to deal with bound and unbound methods. 在python 2中,您必须处理绑定和未绑定的方法。 These do not have a __dict__ attribute, like functions do: 它们没有__dict__属性,就像函数一样:

#python 2
'__dict__' in dir(SomeClass.some_method)
Out[9]: False

def stuff():
    pass

'__dict__' in dir(stuff)
Out[11]: True

In python 3, your code works fine! 在python 3中,您的代码工作正常! The concept of bound/unbound methods is gone, everything is a function. 绑定/非绑定方法的概念已经不复存在,一切都是一个函数。

#python 3
'__dict__' in dir(SomeClass.some_method)
Out[2]: True

Back to making your code work, you need to put the attribute on the thing which has a __dict__ : the actual function: 回到使代码正常工作,您需要将属性放在具有__dict__的东西上:实际功能:

if not hasattr(SomeClass.some_method.__func__, 'some_static_var'):
    #etc

Read more on im_func and __func__ here 在此处阅读有关im_func__func__更多信息

It is up to you to decide whether this makes your code more or less readable - for me, making these types of things class attributes is almost always the way to go; 由您来决定这是否使您的代码更具可读性-对我来说,使这些类型的事情具有类属性几乎总是要走的路。 it doesn't matter that only one method is accessing said attribute, it's where I look for "static" type vars. 不管是哪种方法都可以访问所述属性,这是我寻找“静态”类型vars的地方。 I value readable code over clean namespaces. 我重视可读代码,而不是干净的命名空间。

This last paragraph was of course an editorial, everyone is entitled to their opinion :-) 最后一段当然是社论,每个人都有自己的见解:-)

You can't set attribute on method objects. 您不能在方法对象上设置属性。

Creating class attributes instead (that is, SomeClass.some_var = 1 ) is the standard Python way. 相反,创建属性(即SomeClass.some_var = 1 )是标准的Python方法。 However, we might be able to suggest more appropriate fixes if you give us a high-level overview of your actual problem (what are you writing this code for?). 但是,如果您向我们提供有关实际问题的高级概述(您打算将此代码编写的目的是什么?),我们可能会提出更合适的解决方案。

Use the global keyword to access file-level variables 使用global关键字访问文件级变量

my_static = None

class MyClass(object):
    def some_method(self):
        global my_static
        if my_static is None:
            my_static = 0
        else:
            my_static = my_static + 1
        print my_static

if __name__ == '__main__':
    instance = MyClass()
    instance.some_method()
    instance.some_method()

Outputs: 输出:

0
1

Although, as mentioned elsewhere, a class variable would be preferable 尽管,如其他地方所述,最好使用类变量

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

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