The goal is to wrap a function or method and carry data around with the wrapper that's unique to the wrapped function.
As an example - let's say I have object myThing
with method foo
. I want to wrap myThing.foo
with myWrapper
, and (as an example) I want to be able to count the number of times myThing.foo
is actually called.
So far, the only method I've found to be effective is to just add an attribute to the object -- but this feels a little bit clumsy.
class myThing(object):
def foo(self):
return "Foo called."
def myWrap(some_func):
def _inner(self):
#a wild kludge appears!
try:
self.count += 1
except AttributeError:
self.count = 0
return some_func(self)
return _inner
Stick = myThing()
myThing.foo = myWrap(myThing.foo)
for i in range(0, 10):
Stick.foo() ##outputs "Foo called." 10 times
Stick.count # the value of Stick.count
So, this achieves the goal, and in fact if there are multiple instances of myThing
then each one 'tracks' its own self.count value, which is part of my intended goal. However, I am not certain that adding an attribute to each instance of myThing
is the best way to achieve this. If, for example, I were to write a wrapper for a function that wasn't part of an object or class, adding attributes to an object that isn't there won't do anything.
Maybe there is a hole in my understanding of what's actually happening when a method or function is wrapped. I do know that one can maintain some kind of static data within a closure, as with the following example:
def limit(max_value):
def compare(x):
return x > max_value
return compare
isOverLimit = limit(30)
isOverLimit(45) #returns True
isOverLimit(12) #returns False
alsoOver = limit(20)
alsoOver(25) # returns True
isOverLimit(25) # returns False
The second example proving that it's not simply modifying the original instance of limit
, and that isOverLimit
continues to act as it did before the second alsoOver
is created. So I get the sense that there's a way for the wrapper to carry an incremental variable around with it, and that I'm just missing something obvious.