5

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.

asked Jan 22, 2014 at 17:33
1
  • 1
    What about SomeClass.some_method.im_func.some_static_var = 1 (Assuming python2) Commented Jan 22, 2014 at 18:05

3 Answers 3

3

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 :-)

answered Jan 22, 2014 at 17:58
1

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?).

answered Jan 22, 2014 at 18:03
1
  • 1
    He could put the attribute on the actual function rather than the wrapped method object. Commented Jan 22, 2014 at 18:05
-1

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

answered Jan 22, 2014 at 18:09

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.