<p>我喜欢@Space_C0wb0y的答案,它类似于raymondhettinger发送给我的代码,用于解决pyparsing中类似的情况(见下文)。对于您的简单示例,请尝试使用以下normalizer类包装给定的回调:</p>
<pre><code>class _ArityNormalizer(object):
def __init__(self, fn):
self.baseFn = fn
self.wrapper = None
def __call__(self, value, domain_object):
if self.wrapper is None:
try:
self.wrapper = self.baseFn
return self.baseFn(value, domain_object)
except TypeError:
self.wrapper = lambda v,d: self.baseFn(v)
return self.baseFn(value)
else:
return self.wrapper(value, domain_object)
</code></pre>
<p>您的代码现在可以将回调包装在<code>_ArityNormalizer</code>中,并且在回调时,总是使用2个参数进行调用。<code>_ArityNormalizer</code>只执行一次尝试错误的“使用2个参数调用,如果失败,则使用1个参数调用”逻辑,此后将直接转到正确的形式。在</p>
<p>在pyparsing中,我希望支持可能被定义为接受0、1、2或3个参数的回调,并编写代码,根据回调函数的签名,用几个修饰符之一包装被调用函数。这样,在运行/回调时,我总是用3个参数进行调用,而装饰器负责使用正确数量的参数进行实际调用。在</p>
<p>我的代码做了很多脆弱的/不可移植的/版本敏感的签名自省来完成这项工作(听起来像是操作目前正在做的),直到raymondhettinger给我一个很好的arity裁剪方法,它基本上实现了@Space_C0wb0y的答案所建议的。RH的代码使用了一些非常简洁的修饰符来包装一个非局部变量来记录成功调用的arity,因此您只需经历一次尝试和错误,而不是每次调用回调。您可以在SourceForge上的pyparsing SVN存储库中的函数<code>_trim_arity</code>中看到他的代码—注意,由于使用了“nonlocal”关键字,他的代码有Py2/Py3变体。在</p>
<p>上面的<code>_ArityNormalizer</code>代码的灵感来自RH的代码,在我完全理解他的代码的魔力之前。在</p>