Let say I have some imported class named TheClass and a method sth(arg).
What I have:
var = TheClass()
var.sth('blah')
What I want:
var = TheClass()
var.wrapped_sth()
where wrapped_sth is something like:
def wrapped_sth():
sth('blah')
I already know that it should be done with a decorator, however all the examples I already found were cases where you have access to TheClass implementation, which I don't have and I don't want to override.
Hope the description is clear. Can you help me?
My recommendation would be to extend TheClass to wrap the function.
class MyClass(TheClass):
def wrapped_sth(self):
return self.sth('blah')
Now you can create var = MyClass(), and call var.wrapped_sth() as desired, and MyClass will inherit all the functions from TheClass.
You're coding your decorator incorrectly, to correct that:
def decorator_sth(func):
def wrapper():
return func('blah')
return wrapper
Now wrap the method using decorator_sth:
var.sth = decorator(var.sth) # this call returns wrapper
decorator_sth takes a function and returns a wrapper function. func is the decorated function, wrapper is the wrapper function. The wrapper function retains func from the enclosing scope, from the local scope of decorator_sth.
This is a typical decorator; it takes a function or a callable object as an argument and returns either the callable itself or a wrapper object around it.
Related
Asking just out of curiosity:
Intuitively, I would tend to think that the code below would fail because the __init__ function calls somefunc to populate somevar before the function was defined in the object's body, as would be the case for functions within a module.
Could you explain why this code actually works?
Thanks,
class someobj:
def __init__(self):
self.somevar = self.somefunc()
def somefunc(self):
return 'some_value'
obj = someobj()
print(obj.somevar)
Calling def assigns the function code, variables etc to its name, but doesn't run the internal code. Documentation.
The interpretater looks at this script and says
I'll define a class (basically a namespace)
Inside the class, I'll DEFINE class.init
Another define call; I'll DEFINE class.somefumc
Now the init is called by the constructor and the somefunc method is already defined.
I have a library proving the following code:
class LibClass:
def decorator_method(self, *args, **kwargs):
# some code...
pass
which is intended to be used as follows:
k = LibClass()
method_args = (,) # something I create
#k.decorator_method(method_args)
def my_func():
# Code that I want to run
Specifically, the library implements some callback-like functionality via these decorators. Naturally, I have no control over the library, nor is there any alternative functionality.
Importantly, the instance of LibClass is part of the decorator, so my_func is added to the callbacks of that very instance, k.
However, I have implemented my_func elsewhere in my code and I want to separate the function from the decoration. One way would be to create a wrapper like so:
k = LibClass()
#k.decorator_method(method_args)
def my_func_wrapper():
# Actual call
my_func()
This approach works the way I want, but it has the disadvantage of having to define and call the wrapper function which is not strictly necessary. However, I cannot apparently apply the decorator directly, since
def my_func():
# ...
#k.decorator_method(method_args)
my_func
is not valid python code. Similarly, I might think about decorating a closure in this way, like
def my_func_producer(more_args):
def my_func():
# Do something with more_args
return my_func
where
more_args = (,)
#k.decorator_method(method_args)
my_func_producer(more_args)
is also invalid. Is there any way to apply the decorator without having to define an additional wrapper function?
Instead of this:
def my_func():
# ...
#k.decorator_method(method_args)
my_func
do this:
def my_func():
# ...
my_func = k.decorator_method(method_args)(my_func)
This is doing exactly what the decorator does, but for a minor detail. The "#" syntax for decorators was introduced back in version 2.3 as a syntax sugar to just that: the decorator callable (placed after the #) is called with the function defined starting on the next line as its sole parameter.
So, if we just call the same decorator with the usual calling syntax, passing the function itself as parameter, the effect is the same. In this case we have to rebind the decorated object to the function name, hence the my_func = ... before the call. (the #syntax does an impplicit name binding and that is the "minor detail" I mentioned on the first paragraph)
I'm having trouble understanding the concept of decorators, so basically if I understood correctly, decorators are used to extend the behavior of a function, without modifying the functions code . The basic example:
I have the decorator function, which take as parameter another function and then changes the functionality of the function given as argument:
def decorator(f):
def wrapper(*args):
return "Hello " + str(f(*args))
return wrapper
And here I have the function which I want to decorate :
#decorator
def text (txt):
'''function that returns the txt argument'''
return txt
So if I understand correctly , what actually happens "behind" is:
d=decorator(text)
d('some argument')
My question is , what happens in this case when we have three nested function in the decorator:
def my_function(argument):
def decorator(f):
def wrapper(*args):
return "Hello " +str(argument)+ str(f(*args))
return wrapper
return decorator
#my_function("Name ")
def text(txt):
return txt
Because the functionality is awesome, I can pass argument in the decorator, I do not understand what actually happens behind this call :
#my_function("Name ")
Thank you,
It is just another level of indirection, basically the code is equivalent to:
decorator = my_function("Name ")
decorated = decorator(text)
text = decorated
Without arguments, you already have the decorator, so
decorated = my_function(text)
text = decorated
my_function is used to create a closure here. The argument is local to my_function. But due to closure, when you return the decorator, the decorator function has a reference to it all the time. So when you apply decorator to text, the decorator adds extra functionality, as to be expected. It also can embed argument in its extra functionality since it has access to the environment in which it was defined.
How to use instance as a parameter in the python member function decorators.
The following is an example.
def foo(func):
def wrap(s):
func()
s.ma()
return wrap
class A:
def ma(self):
print "this is ma"
#foo(self) #error.name 'self' is not defined
def mb(self):
print "this is mb"
It's not clear what you're looking for, but if you want to be able to use the reference to the instance inside your decorator:
def foo(func):
def wrap(s): # I'd call this 'self' instead of 's' to remind us it's a reference to an instance
func(s) # This is a function, not a method yet - so we need to pass in the reference
s.ma() # This is a method, because you use attribute lookup on the object s to get it
return wrap
class A:
def ma(self):
print "this is ma"
#foo # if the way foo wraps mb doesn't depend on some arg, don't use args here
def mb(self):
print "this is mb"
I think you're confused here about the difference between methods and functions in Python – you seem to expect func will work like a method, when in fact it will still be a function when it is being decorated. It is the decorated function that will, at attribute lookup on the instance, be turned into a method; this means you still need the explicit self when you call func in your wrapper function.
See the terrific answer to How to make a chain of function decorators? for a better explanation of what's going on.
[Updated]: Answer inline below question
I have an inspecting program and one objective is for logic in a decorator to know whether the function it is decorating is a class method or regular function. This is failing in a strange way. Below is code run in Python 2.6:
def decorate(f):
print 'decorator thinks function is', f
return f
class Test(object):
#decorate
def test_call(self):
pass
if __name__ == '__main__':
Test().test_call()
print 'main thinks function is', Test().test_call
Then on execution:
decorator thinks function is <function test_call at 0x10041cd70>
main thinks function is <bound method Test.test_call of <__main__.Test object at 0x100425a90>>
Any clue on what's going wrong, and if it is possible for #decorate to correctly infer that test_call is a method?
[Answer]
carl's answer below is nearly perfect. I had a problem when using the decorator on a method that subclasses call. I adapted his code to include a im_func comparison on superclass members:
ismethod = False
for item in inspect.getmro(type(args[0])):
for x in inspect.getmembers(item):
if 'im_func' in dir(x[1]):
ismethod = x[1].im_func == newf
if ismethod:
break
else:
continue
break
As others have said, a function is decorated before it is bound, so you cannot directly determine whether it's a 'method' or 'function'.
A reasonable way to determine if a function is a method or not is to check whether 'self' is the first parameter. While not foolproof, most Python code adheres to this convention:
import inspect
ismethod = inspect.getargspec(method).args[0] == 'self'
Here's a convoluted way that seems to automatically figure out whether the method is a bound or not. Works for a few simple cases on CPython 2.6, but no promises. It decides a function is a method if the first argument to is an object with the decorated function bound to it.
import inspect
def decorate(f):
def detect(*args, **kwargs):
try:
members = inspect.getmembers(args[0])
members = (x[1].im_func for x in members if 'im_func' in dir(x[1]))
ismethod = detect in members
except:
ismethod = False
print ismethod
return f(*args, **kwargs)
return detect
#decorate
def foo():
pass
class bar(object):
#decorate
def baz(self):
pass
foo() # prints False
bar().baz() # prints True
No, this is not possible as you have requested, because there is no inherent difference between bound methods and functions. A method is simply a function wrapped up to get the calling instance as the first argument (using Python descriptors).
A call like:
Test.test_call
which returns an unbound method, translates to
Test.__dict__[ 'test_call' ].__get__( None, spam )
which is an unbound method, even though
Test.__dict__[ 'test_call' ]
is a function. This is because functions are descriptors whose __get__ methods return methods; when Python sees one of these in the lookup chain it calls the __get__ method instead of continuing up the chain.
In effect, the 'bound-methodiness' of a function is determined at runtime, not at define-time!
The decorator simply sees the function as it is defined, without looking it up in a __dict__, so cannot tell whether it is looking at a bound method.
It might be possible to do this with a class decorator that modifies __getattribute__, but that's a particularly nasty hack. Why must you have this functionality? Surely, since you have to place the decorator on the function yourself, you could pass it an argument that says whether said function is defined within a class?
class Test:
#decorate( method = True )
def test_call:
...
#decorate( method = False )
def test_call:
...
Your decorator is run before the function becomes a method. def keyword inside a class defines a function line in any other place, then the functions defined in the body of a class are added to the class as methods. Decorator operates on the function before it is processed by the class that is why your code 'fails'.
There is no way for the #decorate to see the function is actually a method. A workaround for that would be to decorate the function whatever it is (e.g. adding an attribute do_something_about_me_if_I_am_a_method ;-)) and then process it again after the class is computed (iterating over the class members and doing whatever you want with those decorated).
I tried a slightly different example, with one decorated method and one undecorated method.
def decorate(f):
print 'decorator thinks function is', f
return f
class Test(object):
#decorate
def test_call(self):
pass
def test_call_2(self):
pass
if __name__ == '__main__':
print 'main thinks function is', Test.test_call
print 'main thinks function 2 is', Test.test_call_2
Then the output is:
decorator thinks function is <function test_call at 0x100426b18>
main thinks function is <unbound method Test.test_call>
main thinks function 2 is <unbound method Test.test_call_2>
Thus, the decorator saw a different type than the main function did, but the decorator did not change the function's type, or it would be different from the undecorated function.