什么是打开和关闭装饰器的最佳方法,而不是实际去每个装饰并将其评论出来?假设您有一个基准测试装饰器:
# deco.py
def benchmark(func):
def decorator():
# fancy benchmarking
return decorator
Run Code Online (Sandbox Code Playgroud)
在你的模块中,例如:
# mymodule.py
from deco import benchmark
class foo(object):
@benchmark
def f():
# code
@benchmark
def g():
# more code
Run Code Online (Sandbox Code Playgroud)
这很好,但有时你不关心基准测试,也不想要开销.我一直在做以下事情.添加另一个装饰者:
# anothermodule.py
def noop(func):
# do nothing, just return the original function
return func
Run Code Online (Sandbox Code Playgroud)
然后注释掉导入行并添加另一行:
# mymodule.py
#from deco import benchmark
from anothermodule import noop as benchmark
Run Code Online (Sandbox Code Playgroud)
现在,基于每个文件切换基准测试,只需要更改相关模块中的import语句.可以独立控制各个装饰器.
有一个更好的方法吗?最好不要编辑源文件,并指定在其他地方使用哪些文件的装饰器.
您可以将条件添加到装饰器本身:
def benchmark(func):
if not <config.use_benchmark>:
return func
def decorator():
# fancy benchmarking
return decorator
Run Code Online (Sandbox Code Playgroud)
小智 5
我一直在使用以下方法。它与 CaptainMurphy 建议的几乎相同,但它的优点是您不需要像函数一样调用装饰器。
import functools
class SwitchedDecorator:
def __init__(self, enabled_func):
self._enabled = False
self._enabled_func = enabled_func
@property
def enabled(self):
return self._enabled
@enabled.setter
def enabled(self, new_value):
if not isinstance(new_value, bool):
raise ValueError("enabled can only be set to a boolean value")
self._enabled = new_value
def __call__(self, target):
if self._enabled:
return self._enabled_func(target)
return target
def deco_func(target):
"""This is the actual decorator function. It's written just like any other decorator."""
def g(*args,**kwargs):
print("your function has been wrapped")
return target(*args,**kwargs)
functools.update_wrapper(g, target)
return g
# This is where we wrap our decorator in the SwitchedDecorator class.
my_decorator = SwitchedDecorator(deco_func)
# Now my_decorator functions just like the deco_func decorator,
# EXCEPT that we can turn it on and off.
my_decorator.enabled=True
@my_decorator
def example1():
print("example1 function")
# we'll now disable my_decorator. Any subsequent uses will not
# actually decorate the target function.
my_decorator.enabled=False
@my_decorator
def example2():
print("example2 function")
Run Code Online (Sandbox Code Playgroud)
在上面,example1 将被修饰,example2 将不会被修饰。当我必须按模块启用或禁用装饰器时,只要我需要不同的副本,我只需创建一个新的 SwitchedDecorator 函数。