我想让两个函数彼此相等,如下所示:
def fn_maker(fn_signature):
def _fn():
pass
_fn.signature = fn_signature
return _fn
# test equality of two function instances based on the equality of their signature values
>>> fa = fn_maker(1)
>>> fb = fn_maker(1)
>>> fc = fn_maker(2)
>>> fa == fb # should be True, same signature values
True
>>> fa == fc # should be False, different signature values
False
我该怎么办?我知道如果fa,fb,fc是某个类的实例,我可能会覆盖eq
和ne
。但是这里 eq 不在dir(fa)中并且添加它列表不起作用。
我想出了一些解决方法,比如使用缓存,例如
def fn_maker(fn_signature):
if fn_signature in fn_maker.cache:
return fn_maker.cache[fn_signature]
def _fn():
pass
_fn.signature = fn_signature
fn_maker.cache[fn_signature] = _fn
return _fn
fn_maker.cache = {}
通过这种方式可以保证相同的签名值只有一个函数(有点像单例)。但我真的在寻找一些更整洁的解决方案。
答案 0 :(得分:6)
如果您将函数转换为覆盖__call__()
的某些类的实例以及比较运算符,那么实现所需的语义将非常容易。
答案 1 :(得分:2)
无法覆盖函数的__eq__
实现(使用Python 2.7测试)
>>> def f():
... pass
...
>>> class A(object):
... pass
...
>>> a = A()
>>> a == f
False
>>> setattr(A, '__eq__', lambda x,y: True)
>>> a == f
True
>>> setattr(f.__class__, '__eq__', lambda x,y: True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'function'
答案 2 :(得分:0)
我认为这不可能。
但是覆盖__call__
似乎是一个很好的解决方案。