If you define and use your own decorator in Python, you may want to be able to pass arguments to the decorator later.
Where to use the original decorator
@my_decorator
def hoge():
# ...
If you implement a general decorator, you'll want to be able to pass arguments to the decorator later. It will be necessary to rewrite all the decorators that were used like ↑ as ↓.
When setting arguments when using a decorator
@my_decorator(arg1='value1')
def hoge():
# ...
Even if you don't need any arguments, you need to put parentheses if the decorator implementation changes.
When no argument is set when using the decorator
@my_decorator()
def hoge():
# ...
Rewriting all the parts that use the decorator is bothersome to modify and verify, so I wanted it to work without the parentheses if no arguments were needed.
I want to create a decorator (my_decorator
) that can dynamically use arguments as shown below.
By the way, I would like to implement it as a decorator for decorators so that such functions can be used universally.
python
#With no arguments
@my_decorator
def hoge():
pass
#With arguments
@my_decorator(arg1='value1')
def fuga():
pass
Implement a decorator that dynamically interprets the arguments to apply to the decorator, as shown below.
decorators.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import functools
def dynamic_args(func0):
def wrapper(*args, **kwargs):
if len(args) != 0 and callable(args[0]):
#When a function is passed as the first argument:Treat as a decorator with no arguments
func = args[0]
return functools.wraps(func)(func0(func))
else:
#Other:Treat as a decorator with arguments
def _wrapper(func):
return functools.wraps(func)(func0(func, *args, **kwargs))
return _wrapper
return wrapper
If you prepare a decorator like the one above, you can achieve your purpose simply by defining your own decorator as follows.
python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from decorators import dynamic_args
#Apply the decorator created above to your decorator
@dynamic_args
def my_decorator(func, arg1='default_value1', arg2='default_value2'):
def wrapper(*args, **kwargs):
#Defined arguments(arg1, arg2)Write the process you want to actually do using
# ...
return wrapper
As a sample, create a decorator named my_decorator
that puts parentheses before and after the return value (string).
sample.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from decorators import dynamic_args
#####################
#Your own decorator definition#
#####################
@dynamic_args
def my_decorator(func, before='「', after='」'):
def wrapper(*args, **kwargs):
return "{} {} {}".format(before, func(*args, **kwargs), after)
return wrapper
##########################
#Example of using a decorator with no arguments#
##########################
@my_decorator
def func_without_args():
return "Argumentless decorator"
print(func_without_args()) # output:"Decorator with no arguments"
##########################
#Example of using a decorator with arguments#
##########################
@my_decorator(before='『', after='』')
def func_with_args():
return "Decorator with arguments"
print(func_with_args()) # output:"Decorator with arguments"
####################################
#An example of applying a decorator to a predefined function#
####################################
def func_without_decorator():
return "No decorator"
print(my_decorator(func_without_decorator)()) # output:"No decorator"
print(my_decorator(before="『", after="』")(func_without_decorator)()) # output:"No decorator"
Python Tips: I want to pass arguments to the decorator-Life with Python http://www.lifewithpython.com/2016/09/python-decorator-with-arguments.html
Python Decorator Expressions (2)-When decorators have arguments and you want to apply multiple decorators | Immediately forget your brain notes for that http://jutememo.blogspot.jp/2008/10/python-2.html
python - AttributeError: 'str' object has no attribute 'module' - Stack Overflow http://stackoverflow.com/questions/18493879/attributeerror-str-object-has-no-attribute-module
Recommended Posts