In a Python method, I would like to have a local variable whose value persists between calls to the method.
This question shows how to declare such "static variables" (c++ terminology) inside functions. 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:
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
. 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.
In python 2, you have to deal with bound and unbound methods. These do not have a __dict__
attribute, like functions do:
#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! 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:
if not hasattr(SomeClass.some_method.__func__, 'some_static_var'):
#etc
Read more on im_func
and __func__
here
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. 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. 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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.