Lin*_*Lin 15 python python-decorators
我正在使用来自两个不同库的两个不同的装饰器.让我们说:@decorator1(param1, param2)和@decorator2(param3, param4).我经常在许多功能中使用:
from moduleA import decorator1
from moduleB import decorator2
@decorator2(foo='param3', bar='param4')
@decorator1(name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...
Run Code Online (Sandbox Code Playgroud)
由于它每次都会发生,我想创建一个处理它们的自定义装饰器.就像是:
@mycustomdecorator(name='param1', state='param2',
foo='param3', bar='param4')
def myfunc(funcpar1, funcpar2):
...
Run Code Online (Sandbox Code Playgroud)
我如何实现这一目标?
Glo*_*eye 13
我认为你不应该 - 使用装饰器的原始名称提供更好的可读性.
但是,如果你真的想,你可以这样做:
import functools
from moduleA import decorator1
from moduleB import decorator2
def my_decorator(foo, bar, name, state):
def inner(func):
@decorator2(foo=foo, bar=bar)
@decorator1(name=name, state=state)
@functools.wraps(func) # Not required, but generally considered good practice
def newfunc(*args, **kwargs)
return func(*args, **kwargs)
return newfunc
return inner
@my_decorator(foo='param3', bar='param4', name='param1', state='param2')
def myfunc(funcpar1, funcpar2):
...
Run Code Online (Sandbox Code Playgroud)
根据评论,这里是另一种方法:
def my_decorator(foo, bar, name, state):
def inner(func):
# Please note that for the exact same result as in the other one,
# the order of decorators has to be reversed compared to normal decorating
newfunc = decorator1(name=name, state=state)(func)
newfunc = decorator2(foo=foo, bar=bar)(newfunc)
# Note that functools.wraps shouldn't be required anymore, as the other decorators should do that themselves
return newfunc
return inner
Run Code Online (Sandbox Code Playgroud)
对某些人来说,这可能看起来更简单.然而,有Python经验的人习惯于使用@来应用装饰器 - 即使仅仅因为这个原因,我更喜欢我的第一个选项.我知道我第一次阅读这段代码需要花费三倍的时间来理解它的作用.
它真的很简单 - 只需编写一个装饰器,它返回另一个装饰器,它将使用其他两个装饰器装饰它的内部函数;)
为了良好的习惯,使用functools.wraps也许是个好主意.它是标准库,可以帮助调试和使用交互式控制台:https://docs.python.org/3.7/library/functools.html
一般来说,我会说一个额外的代码行更值得分别使用装饰器的清晰度.当你在3个月内阅读自己的代码时,你会感谢你自己.
| 归档时间: |
|
| 查看次数: |
814 次 |
| 最近记录: |