I would like to make a decorator which could be used with or without a parameter : Something like this :
class d(object): def __init__(self,msg='my default message'): self.msg = msg def __call__(self,fn): def newfn(): print self.msg return fn() return newfn @d('This is working') def hello(): print 'hello world !' @d def too_bad(): print 'does not work'
In my code, only the use of decorator with parameter is working: How to proceed to have both working (with and without parameter)?
By Params Keyword: You can implement optional parameters by using the params keyword. It allows you to pass any variable number of parameters to a method. But you can use the params keyword for only one parameter and that parameter is the last parameter of the method.
The syntax for decorators with parameters : Inside the inner function, required operations are performed and the actual function reference is returned which will be assigned to func_name. Now, func_name() can be used to call the function with decorator applied on it.
So, here in this post, we are going to learn about Decorator Chaining. Chaining decorators means applying more than one decorator inside a function. Python allows us to implement more than one decorator to a function.
Implementing Decorator Arguments You may expect that decorator arguments are somehow passed into the function along with this f argument, but sadly Python always passes the decorated function as a single argument to the decorator function.
I found an example, you can use @trace
or @trace('msg1','msg2')
: nice!
def trace(*args): def _trace(func): def wrapper(*args, **kwargs): print enter_string func(*args, **kwargs) print exit_string return wrapper if len(args) == 1 and callable(args[0]): # No arguments, this is the decorator # Set default values for the arguments enter_string = 'entering' exit_string = 'exiting' return _trace(args[0]) else: # This is just returning the decorator enter_string, exit_string = args return _trace
If you want to take parameters to your decorator, you need to always call it as a function:
@d() def func(): pass
Otherwise, you need to try to detect the difference in parameters--in other words, you need to magically guess what the caller means. Don't create an API that needs to guess; consistently say what you mean to begin with.
In other words, a function should either be a decorator, or a decorator factory; it shouldn't be both.
Note that if all you want to do is store a value, you don't need to write a class.
def d(msg='my default message'): def decorator(func): def newfn(): print msg return func() return newfn return decorator @d('This is working') def hello(): print 'hello world !' @d() def hello2(): print 'also hello world'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With