python - 比较包装函数是否是装饰器的实例
问题描述
我有decorator1
和decorator2
功能。我正在使用这些来装饰一个功能。
@decorator1("some", "args")
@decorator2(1,2)
@decorator1()
def my_func(): print("my func")
当我一遍又一遍地迭代调用包装函数时,输出变成这样:
对于my_func.__wrapped__
:
decorator1
decorator2
decorator1
my func
对于my_func.__wrapped__.__wrapped__()
:
decorator2
decorator1
my func
问题是每个包装函数的名称都是my_func
. 我想检查这个链中的一个函数是否是 let say 的实例decorator1
。我想知道这一点,因为我将使用装饰器的参数。(我已经通过使用__closure__
单元了解它们。)
澄清
我决定举例说明我的目的。
@route("/index")
def index(): pass
@route("/settings")
@need_permission("admin")
def settings: pass
@route("/blog")
@need_permission("admin", "user")
def blog(): pass
我可以在其他地方获得所有这些路由功能,并且我想提取哪个需要哪些权限。
这是我的发现:
>>> blog()
route blog
permissions admin user
>>> blog.__closure__[0].cell_contents
('/blog',)
>>> blog.__closure__[1].cell_contents()
permissions admin user
>>> blog.__closure__[0].cell_contents.__closure__[0].cell_contents
('admin', 'user')
>>> blog.__closure__[0].cell_contents.__closure__[1].cell_contents()
>>>
我只想提取拥有权限的元组。我可以按特定顺序应用我的装饰器并轻松提取,或者我需要DecoratorApplier
像@Poolka 指出的那样实现我的功能。如果没有办法知道第一个选项,我将遵循第二个。
解决方案
instance of a decorator
- 用函数和常规函数实现的装饰器都只是类型的函数function
。
不确定你到底想得到什么。下面的代码是我将如何解决这个问题。基本上,我将属性添加primal_type
到装饰嘉年华所涉及的所有功能中,以存储功能/装饰器的名称。我使用另一个名为DecoratorApplier
. 该代码似乎执行与问题中的问题相关的操作。
编辑
添加的说明并没有使一切都清楚。我想以这种方式混合函数和装饰器逻辑并不是一个好习惯。也许还有另一种选择可以在函数中获取所需的信息?无论如何,下面是我原始方法的两个修改版本(oda
代表可选的装饰器参数)。
(1) - 与DecoratorApplier
import functools
def decorator_1(*d1_args, **d1_kwargs):
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print('inside decorator_1', d1_args, d1_kwargs)
return func(*args, **kwargs)
return wrapped
return decorator
def decorator_2(*d2_args, **d2_kwargs):
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print('inside decorator_2', d2_args, d2_kwargs)
return func(*args, **kwargs)
return wrapped
return decorator
class DecoratorApplier:
def __init__(self, *decorators):
self.decorators = decorators
def __call__(self, func):
func.oda = dict()
for decorator in self.decorators:
func = decorator[0](*decorator[1], **decorator[2])(func)
(
func
.oda
.setdefault(decorator[0].__name__, list())
.extend([decorator[1], decorator[2]])
)
return func
@DecoratorApplier(
(decorator_1, (1, 2), {'x': 10, 'y': 20}),
(decorator_2, tuple(), dict()))
def f_1():
print('inside f_1')
print(f_1.oda)
return
if __name__ == '__main__':
f_1()
(2) - 修改原始装饰器
import functools
def decorator_1(*d1_args, **d1_kwargs):
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print('inside decorator_1', d1_args, d1_kwargs)
(
kwargs
.setdefault('oda', dict())
.setdefault('decorator_1', list())
.extend([d1_args, d1_kwargs])
)
return func(*args, **kwargs)
return wrapped
return decorator
def decorator_2(*d2_args, **d2_kwargs):
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
print('inside decorator_2', d2_args, d2_kwargs)
(
kwargs
.setdefault('oda', dict())
.setdefault('decorator_2', list())
.extend([d2_args, d2_kwargs])
)
return func(*args, **kwargs)
return wrapped
return decorator
@decorator_1(1, 2, x=10, y=20)
@decorator_2()
def f_1(oda=None):
print('inside f_1')
print(' oda', oda)
return
if __name__ == '__main__':
f_1()
推荐阅读
- c++ - Googletest (gtest) / googlemock (gmock):为什么“interleav[ing] `EXPECT_CALL()`s and calls to the mock functions”未定义行为?
- python - 将python行值与以前的(重复)进行比较
- smtp - phpmailer 问题 - smtp.office365.co.uk 连接失败
- r - 具有 kruskal wallis 检验 p 值的 Dplyr 表
- java - UnsolvableVersionConflictException 更新 apache 梁版本
- opencart - opencart 客户事件,未在管理端调用
- python - 计算来自外部来源的数据
- java - 根据类用途分配正确的包
- oauth - 使用 FusionAuth 的多租户 OAuth
- flutter - in_app_purchase purchaseUpdatedStream 监听事件未触发