python - 如何在不使用 @ 语法的情况下使用“双层”装饰器?
问题描述
假设我有这个装饰器:
def decorator_with_args(decorator_arg1, decorator_arg2):
def decorator(func):
def wrapped(*args, **kwargs):
if decorator_arg1 == 'arg1' and decorator_arg2 == 'arg2':
return func(*args, **kwargs)
return wrapped
return decorator
通常你会像这样装饰一个函数:
@decorator_with_args('arg1', 'arg2')
def function():
return 'foo'
>>> foo = function()
'foo'
如何在不使用@
语法的情况下调用它?
我知道如果它只是一个单层装饰器(即没有 args 的装饰器),那么你调用它的方式就是你将它包装在装饰器函数中,如下所示:
>>> foo = decorator(function)
'foo'
注意function
没有被调用。如果装饰器和函数都有需要传递的参数,这将如何工作?
>>> foo = decorator_with_args(decorator(wrapped_function))
但是那么装饰器的*args
and**kwargs
和原始函数去哪里了呢?
解决方案
decorator_with_args()
是一个装饰器工厂——也就是说,一个返回装饰器的函数。这意味着为了在没有@
语法的情况下使用它,您需要使用其参数调用它,然后使用您的函数作为参数调用结果。
看起来是这样的:
def function():
return 'foo'
function = decorator_with_args('arg1', 'arg2')(function)
>>> function()
'foo'
请注意,这类似于使用带有或不带有@
语法的常规装饰器之间的区别:
@deco
def func(arg):
# ...
是
def func(arg):
# ...
func = deco(func)
作为
@deco_fac(x, y)
def func(arg):
# ...
是
def func(arg):
# ...
func = deco_fac(x, y)(func)
推荐阅读
- compilation - GLib:替换已弃用的 g_tree_traverse() 函数?
- java - 异步调用 API java
- java - 容器未显示在 JScrollPane 中
- ios - 如何在 SiriusObfuscator 中给出路径?
- javascript - 我的 headerStyle 不起作用。我尝试分配背景颜色,但运行时它没有出现
- amazon-web-services - 从 AWS 组织导出所有 IAM 用户、角色和策略
- docker-compose - docker-compose:如何将秘密传递给logstash中的环境变量?
- blazor - FxCop Analyzers 是否适用于 blazor 项目?
- java - 没有 Thread.sleep 死锁实现不起作用
- search - Vim 在整个项目中查找和替换多行