如何解决部分应用/和/或/柯里化的装饰器:如何确定是否提供了强制参数?
我最近一直在修改装饰器,并且(作为学术练习)尝试实现一个装饰器,允许部分应用和/或装饰函数的柯里化。此外,这个装饰器应该是可选参数化的,并采用一个 kwarg asap
来确定装饰函数是否应该在获得所有必需的 args/kwargs 后立即返回(默认:asap=True
)或者装饰函数是否应该保留缓存 args/kwargs,直到不带参数调用函数 (asap=False
)。
这是我想出的装饰器:
def partialcurry(_f=None,*,asap: bool=True):
""" Decorator; optionally parameterizable; Allows partial application /and/or/ currying of the decorated function F. Decorated F fires as soon as all mandatory args and kwargs are supplied,or,if ASAP=False,collects args and kwargs and fires only if F is called without args/kwargs. """
def _decor(f,*args,**kwargs):
_all_args,_all_kwargs = list(args),kwargs
@functools.wraps(f)
def _wrapper(*more_args,**more_kwargs):
nonlocal _all_args,_all_kwargs # needed for resetting,not mutating
_all_args.extend(more_args)
_all_kwargs.update(more_kwargs)
if asap:
try:
result = f(*_all_args,**_all_kwargs)
# reset closured args/kwargs caches
_all_args,_all_kwargs = list(),dict()
except TypeError:
result = _wrapper
return result
elif not asap:
if more_args or more_kwargs:
return _wrapper
else:
result = f(*_all_args,**_all_kwargs)
# again,reset closured args/kwargs caches
_all_args,dict()
return result
return _wrapper
if _f is None:
return _decor
return _decor(_f)
### examples
@partialcurry
def fun(x,y,z=3):
return x,z
print(fun(1)) # preloaded function object
print(fun(1,2)) # all mandatory args supplied; (1,1,2); reset
print(fun(1)(2)) # all mandatory args supplied; (1,2,3); reset
print()
@partialcurry(asap=False)
def fun2(x,z
print(fun2(1)(2,3)) # all mandatory args supplied; preloaded function object
print(fun2()) # fire + reset
print(fun2(1)(2)) # all mandatory args supplied; preloaded function object
print(fun2(4)()) # load one more and fire + reset
我确信这通常可以改进(例如,将它作为一个类来实现是一个好主意)并且非常感谢任何建议,但是我的主要问题是如何确定是否提供了所有强制性参数/kwargs,因为我觉得检查 TypeError
太笼统了,可以捕获所有类型的 TypeError
。一个想法是定义一个辅助函数来计算强制参数的数量,可能是这样的:
def _required_args_cnt(f):
""" Auxiliary function: Calculate the number of /required/ args of a function F. """
all_args_cnt = f.__code__.co_argcount + f.__code__.co_kwonlyargcount
def_args_cnt = len(f.__defaults__) if f.__defaults__ else 0
return all_args_cnt - def_args_cnt
明显不满意..
非常感谢任何建议!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。