Decorator which conditionally activates another decorator?
我有一些函数,在正常情况下,通过用户输入提供的参数调用这些函数。但是,使用一系列参数调用其中一些函数是有效的,这些参数是在运行时根据某些系统状态确定的。
我希望用户能够有选择地指示我的程序使用所有有效输入调用这些函数,并返回每次调用的结果。我认为一个decorator类似于一个函数的激活开关,这个函数有另一个decorator,它指示要使用的参数系列会很好地工作。
另外,我需要保留函数签名和元数据。这对我的程序的运行至关重要。
这是我试过的,但不起作用。它基于这个例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | >>> from decorator import decorator >>> def the_list(): ... return ["foo","bar","baz"] ... >>> import itertools >>> @decorator ... def do_all(func): ... # this will do nothing (besides wrap in a tuple) unless func is decorated with @gets_arg_from ... if hasattr(func, 'get_from'): ... return tuple(func(*args) for args in itertools.product(*(list_fun() for list_fun in func.get_from))) ... else: ... return (func(),) ... >>> def gets_arg_from(*list_funcs): ... # this will do nothing to func unless decorated with @do_all ... def gets_arg_from(func, *args, **kwargs): ... func.get_from = list_funcs ... return func(*args, **kwargs) ... return decorator(gets_arg_from) ... >>> @gets_arg_from(the_list) ... def print_func(word): ... # this will print its argument unless decorated with @do_all ... # at that point it will print every element returned by the_list() ... print word ... >>> print_func("foo") foo >>> all = decorator(do_all, print_func) >>> all() Traceback (most recent call last): File"<stdin>", line 1, in <module> TypeError: print_func() takes exactly 1 argument (0 given) >>> print_func.get_from Traceback (most recent call last): File"<stdin>", line 1, in <module> AttributeError: 'function' object has no attribute 'get_from' |
我所期望的是:
1 2 | >>> all() ("foo","bar","baz") |
号
我注意到的是错误的:
至于我的动机,我之所以想到装饰器,是因为实际上有数百个这样的例程,它们的实现细节(以及它们的功能正确性)会经常发生变化,我不想使用
这不是你想要的吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import functools from itertools import product def the_list(): return ["foo","bar","baz"] def do_all(func): if hasattr(func, 'get_from'): @functools.wraps(func) def wrapper(*args, **kwargs): return tuple(func(*args) for args in product(*(lf() for lf in func.get_from))) return wrapper return func def gets_arg_from(*list_funcs): def decorator(func): func.get_from = list_funcs return func return decorator @gets_arg_from(the_list) def print_func(word): return word print print_func('foo') all = do_all(print_func) print all() |
编辑:解释
这两个代码段是相同的:
1 2 3 | @deco def func(...): some code |
号
与
1 | func = deco(lambda ...: some code) |
@有些东西只是函数调用和匿名函数创建的一种句法糖分…
我将逐步解释下一个代码和平时期发生的事情:
1 2 3 | @gets_arg_from(the_list) def print_func(word): return word |
。
第一个python创建一个异常函数,它接收一个参数
然后调用函数
从
类似的效果可以通过以下方式实现:
1 2 3 4 | def __anonimous(word): return word __decorator = gets_arg_from(the_list) print_func = __decorator(__anonimous) |
所以基本上,
另一方面,
你可以在这里找到更多的例子。