Python - Static Variable inside Function - python

I am trying to set a static variable inside a function. Essentially, I want this variable to be false initially. After the first time this function is called, I want the variable to be set to true.
I currently have the following:
class LKTracker(object):
def track_points(self,width,height):
if not hasattr(track_points, "gotInitialFeatures"):
track_points.gotInitialFeatures = None
if not track_points.gotInitialFeatures:
#do some stuff
track_points.gotInitialFeatures = True
With this code, I keep receiving the following error:
NameError: global name 'track_points' is not defined
Anyone know what is happening here?

In a global function, you can refer directly to the function object by looking up the name.
This does not work in a method; you'd have to look the method up on the class instead:
LKTracker.track_points
This still won't do what you want, however, because you'd get a unbound method object at that moment:
>>> LKTracker.track_points
<unbound method LKTracker.track_points>
Method objects are created on demand (because functions are descriptors), and creating an attribute on a method object is futile; they generally only live for a short while.
You'd need to access the function instead:
>>> LKTracker.track_points.__func__
<function track_points at 0x103e7c500>
but you can do the same thing on self:
self.track_points.__func__
Now you can add a attribute:
track_points = self.track_points.__func__
if not hasattr(track_points, "gotInitialFeatures"):
track_points.gotInitialFeatures = None
if not track_points.gotInitialFeatures:
#do some stuff
track_points.gotInitialFeatures = True
But it would be much easier to just store that attribute on the class instead:
if not hasattr(LKTracker, 'gotInitialFeatures'):

You shall init static variable before call a function.
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
and now you can:
#static_var("gotInitialFeatures", False)
def track_points(self, width, height):
...

Related

Difference between using the decorator and the function with staticmethod

I am trying to create a class which gets given a function, which will then be run from that instance. However, when I tried to use staticmethod, I discovered that there is a difference between using the decorator and just passing staticmethod a function.
class WithDec():
def __init__(self):
pass
#staticmethod
def stat(val):
return val + 1
def OuterStat(val):
return val + 1
class WithoutDec():
def __init__(self, stat):
self.stat = staticmethod(stat)
With these two classes, the following occurs.
>>> WithDec().stat(2)
3
>>> WithoutDec(OuterStat).stat(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable
What is going on, and what can I do to stop it.
Static methods still work through the descriptor protocol, meaning that when it is a class attribute, accessing it via an instance still means that the __get__ method will be called to return an object that actually gets called. That is,
WithDec().stat(2)
is equivalent to
w = WithDec()
w.stat(2)
which is equivalent to
WithDec.stat.__get__(w, WithDec)(2)
However, the descriptor protocol is not invoked when the static method is an instance attribute, as is the case with WithoutDec. In that case
WithoutDec().stat(2)
tries to call the literal staticmethod instance stat, not the the function returned by stat.__get__.
What you wanted was to use staticmethod to create a class attribute, just not via decorator syntax:
class WithoutDec():
def stat(val):
return val + 1
stat = staticmethod(stat)
You first bind stat to a regular function (it's not really an instance method until you try to use it as an instance method), then replace the function with a staticmethod instance wrapping the original function.
The problem is that you are trying to use staticmethod() inside __init__, which is used to create an instance of the class, instead of at the class level directly, which defines the class, its methods and its static methods.
This code works:
def OuterStat(val):
return val + 1
class WithoutDec():
stat = staticmethod(OuterStat)
>>> WithoutDec.stat(2)
3
Note that trying to create an instance of WithoutDec with its own, different, version of stat, is contrary to the meaning of a method being static.
I found a very inspiring solution on this thread. Indeed your code is not very pythonic, and attributes a static method to an attribute of an instance of your class. The following code works:
class WithoutDec():
stat = None
#staticmethod
def OuterStat(val):
return val + 1
then you call:
my_without_dec = WithoutDec()
my_without_dec.stat = WithotuDec.OuterStat
my_without_dec.stat(2)
later if you want to create a new method, you call:
def new_func(val):
return val+1
WithoutDec.newStat = staticmethod(new_func)
my_without_dec.stat = WithoutDec.newStat
my_without_dec.stat(2)
Yes -
In this case, you just have to add the function as an attribute of the instance, it will work as expected, no need for any decorators:
def OuterStat(val):
return val + 1
class WithoutDec():
def __init__(self, stat):
self.stat = stat
The thing is: there is a difference if a function is an attribute of the class or an attribute of the instance. When it is set inside an instance method with self.func = X, it becomes an instance attribute - Python retrieves it the way it was stored, with no modifications, and it is simply another reference to the original function that can be called.
When a function is stored as a class attibute, instead, the default behavior is that it is used as an instance method: upon retrieving the function from an instance, Python arranges things so that self will be injected as the first argument to that function. In this case, the decorators #classmethod and #staticmethod exist to modify this behavior (injetct the class for classmethod or make no injection for staticmethod).
The thing is that staticmethod does not return a function - it returns a descriptor to be used as a class attribute, so that when the decorated function is retrieved from a class, it works as a plain function.
(Internal detail: all 3 behaviors: instance method, classmethod and staticmethod are implementing by having an appropriate __get__ method on the object that is used as an attribute to the class).
NB: There were some discussions in making "staticmethod" to become itself "callable", and simply call the wrapped function - I just checked it made it into Pythonn 3.10 beta 1. This means that your example code will work as is for Python 3.10 - nonetheless, the staticmethod call there is redundant, as stated in the beggining of this answer, and should not be used.

Is it possible to call a static method from withing another static method

Is it possible to call a static method from within another static method?
I tried this:
class MyClass(object):
#staticmethod
def static_method_1(x):
x = static_method_2(x)
print x
#staticmethod
def static_method_2(x):
return 2*x
This returns
NameError: name 'static_method_2' is not defined
Staticmethods are called via the class: MyClass.static_method_2(x).
You probably don't want a staticmethod at all, but a classmethod. These are called the same way but get a reference to the class, which you can then use to call the other method.
class MyClass(object):
#classmethod
def static_method_1(cls, x):
x = cls.static_method_2(x)
print x
#classmethod
def static_method_2(cls, x):
return 2*x
Note, in Python you wouldn't ever do this. There's usually no reason to have a class unless it is storing state. These would probably both be best as standalone functions.
A static method must be invoked via the class that defines it; otherwise, that's just about the only difference between it and a regular function.
#staticmethod
def static_method_1(x):
x = MyClass.static_method_2(x)
print x
The reason is that the name static_method_2 isn't defined in the global scope, or in any other non-local scope (remember, a class does not define a new scope). The static method is simply an attribute of MyClass, and has to be accessed as such.

Get owner instance of attribute

I want to get the instance handle of an attribute when this attribute is passed to a function without its instance. To make it more clear see the example code below:
class aClass():
def __init__(self):
self.anInstanceAttribute = 'ok'
def aFunction(anInstanceAttribute):
print(anInstanceAttribute)
#how to get the instance handle ('the self') of the anInstanceAttribute?
a = aClass()
aFunction(a.anInstanceAttribute)
This is not possible without introspection/frame hacks.
aFunction(a.anInstanceAttribute)
The function arguments are fully evaluated before calling the function. So, the function receives the string object "ok" and knows nothing about the instance a. If you want the function to know something about the instance, then pass in a instead.

Do class/static variables have access to static methods?

Forgive me if this question is obvious, but from what I've read on Python's OOP tutorials none of them mention how to have a static variable store a static method. In my code I tried:
class Features:
a_static_variable = 1
a_static_variable_that_references_a_static_function = Features.func1
#staticmethod
def func1(blah):
print(blah)
When trying to run this I received:
NameError: name 'Features' is not defined
Is it possible for a class method to reference a static method in its own class? If so, how do I do this. I tried replacing Features with nothing and self but as I expected those made no sense as well.
This is simply a case of func1 not being defined yet.
It should work if you reorder:
class Features:
a_static_variable = 1
#staticmethod
def func1(blah):
print(blah)
a_static_variable_that_references_a_static_function = func1
Yes, just define the function first:
class Features:
#staticmethod
def func1(blah):
print(blah)
a_static_variable = 1
a_static_variable_that_references_a_static_function = func1
Features.a_static_variable_that_references_a_static_function('test')
Your code has two errors (explained in the other answers). This example may help you understand what's going on.
class Example:
class_variable = 'class_variable'
#staticmethod
def static_method():
print('static_method')
class_method = static_method
print(locals())
def instance_method(self):
print(instance_method)
print(locals())
When this code is run, without instantiating a member of this class, the output is:
creating the class:
{'class_variable': 'class_variable',
'__module__': '__main__',
'static_method': <staticmethod object at 0x0135E5F0>,
'class_method': <staticmethod object at 0x0135E5F0>
}
So, while creating the class, a scope is created in which all of the names in that dictionary are accessible.
Now let's look at what happens when we do this:
example = Example()
example.instance_method()
Nothing happens when you instantiate an object, but calling instance_method will print the local variable(s) accessible to that scope.
instance_method
{'self': <__main__.Example instance at 0x01810210>}
Now, you are probably used to creating instance methods that reference class variables.
def other_instance_method(self):
print(Example.class_variable)
Here, Example is not present in the local scope. In order to find it, the global scope needs to be searched (i.e. globals). Note that instead of explicitly referencing Example, we could access the the class variable from the self object itself.
def other_instance_method(self):
print(self.class_variable)
You can do some testing yourself by printing locals() and globals() from various places to get a grip on how the scope changes.

Using class/static methods as default parameter values within methods of the same class

I'd like to do something like this:
class SillyWalk(object):
#staticmethod
def is_silly_enough(walk):
return (False, "It's never silly enough")
def walk(self, appraisal_method=is_silly_enough):
self.do_stuff()
(was_good_enough, reason) = appraisal_method(self)
if not was_good_enough:
self.execute_self_modifying_code(reason)
return appraisal_method
def do_stuff(self):
pass
def execute_self_modifying_code(self, problem):
from __future__ import deepjuju
deepjuju.kiss_booboo_better(self, problem)
with the idea being that someone can do
>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)
and also get some magical machine learning happening; this last bit is not of particular interest to me, it was just the first thing that occurred to me as a way to exemplify the use of the static method in both an in-function context and from the caller's perspective.
Anyway, this doesn't work, because is_silly_enough is not actually a function: it is an object whose __get__ method will return the original is_silly_enough function. This means that it only works in the "normal" way when it's referenced as an object attribute. The object in question is created by the staticmethod() function that the decorator puts in between SillyWalk's is_silly_enough attribute and the function that's originally defined with that name.
This means that in order to use the default value of appraisal_method from within either SillyWalk.walk or its caller, we have to either
call appraisal_method.__get__(instance, owner)(...) instead of just calling appraisal_method(...)
or assign it as the attribute of some object, then reference that object property as a method that we call as we would call appraisal_method.
Given that neither of these solutions seem particularly Pythonicâ„¢, I'm wondering if there is perhaps a better way to get this sort of functionality. I essentially want a way to specify that a method should, by default, use a particular class or static method defined within the scope of the same class to carry out some portion of its daily routine.
I'd prefer not to use None, because I'd like to allow None to convey the message that that particular function should not be called. I guess I could use some other value, like False or NotImplemented, but it seems a) hackety b) annoying to have to write an extra couple of lines of code, as well as otherwise-redundant documentation, for something that seems like it could be expressed quite succinctly as a default parameter.
What's the best way to do this?
Maybe all you need is to use the function (and not the method) in the first place?
class SillyWalk(object):
def is_silly_enough(walk):
return (False, "It's never silly enough")
def walk(self, appraisal_function=is_silly_enough):
self.do_stuff()
(was_good_enough, reason) = appraisal_function(self)
if not was_good_enough:
self.execute_self_modifying_code(reason)
return appraisal_function
def do_stuff(self):
pass
def execute_self_modifying_code(self, problem):
deepjuju.kiss_booboo_better(self, problem)
Note that the default for appraisal_function will now be a function and not a method, even though is_silly_enough will be bound as a class method once the class is created (at the end of the code).
This means that
>>> SillyWalk.is_silly_enough
<unbound method SillyWalk.is_silly_enough>
but
>>> SillyWalk.walk.im_func.func_defaults[0] # the default argument to .walk
<function is_silly_enough at 0x0000000002212048>
And you can call is_silly_enough with a walk argument, or call a walk instance with .is_silly_enough().
If you really wanted is_silly_enough to be a static method, you could always add
is_silly_enough = staticmethod(is_silly_enough)
anywhere after the definition of walk.
I ended up writing an (un)wrapper function, to be used within function definition headers, eg
def walk(self, appraisal_method=unstaticmethod(is_silly_enough)):
This actually seems to work, at least it makes my doctests that break without it pass.
Here it is:
def unstaticmethod(static):
"""Retrieve the original function from a `staticmethod` object.
This is intended for use in binding class method default values
to static methods of the same class.
For example:
>>> class C(object):
... #staticmethod
... def s(*args, **kwargs):
... return (args, kwargs)
... def m(self, args=[], kwargs={}, f=unstaticmethod(s)):
... return f(*args, **kwargs)
>>> o = C()
>>> o.s(1, 2, 3)
((1, 2, 3), {})
>>> o.m((1, 2, 3))
((1, 2, 3), {})
"""
# TODO: Technically we should be passing the actual class of the owner
# instead of `object`, but
# I don't know if there's a way to get that info dynamically,
# since the class is not actually declared
# when this function is called during class method definition.
# I need to figure out if passing `object` instead
# is going to be an issue.
return static.__get__(None, object)
update:
I wrote doctests for the unstaticmethod function itself; they pass too. I'm still not totally sure that this is an actual smart thing to do, but it does seem to work.
Not sure if I get exactly what you're after, but would it be cleaner to use getattr?
>>> class SillyWalk(object):
#staticmethod
def ise(walk):
return (False, "boo")
def walk(self, am="ise"):
wge, r = getattr(self, am)(self)
print wge, r
>>> sw = SillyWalk()
>>> sw.walk("ise")
False boo

Categories