【问题标题】:Test equality of two functions in python在python中测试两个函数的相等性
【发布时间】:2012-05-29 07:21:05
【问题描述】:

我想让两个函数相等,像这样:


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 是某个类的实例,我可能会覆盖 <strong>eq</strong><strong>ne</strong>。但是这里 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 = {}

通过这种方式可以保证相同的签名值只有一个函数(有点像单例)。但我真的在寻找一些更简洁的解决方案。

【问题讨论】:

  • 请描述您要解决的问题。可能有更简单的方法。
  • 是的,@ms4py,感谢您指出这一点。对于我正在处理的问题,可能有更简单的解决方案,比如使用类而不是函数。但我真正想学习的是如何在 python 中“覆盖”== 函数的行为,否则根本不可能。
  • 不,我认为应该有一个比比较函数更通用的解决方案,不管你在技术上如何做。你能描述一下你为什么要比较它们吗?
  • 你不能覆盖__eq__的功能,请看下面我的回答。

标签: python function metaprogramming equality


【解决方案1】:

如果您将您的函数转换为覆盖__call__() 以及比较运算符的某个类的实例,那么很容易实现您想要的语义。

【讨论】:

  • 是的,感谢您的提示。但我想知道如果不将它包装在一个对象中,我能走多远,就像我们可以用 Ruby 中的函数做的那样。
【解决方案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'

【讨论】:

    【解决方案3】:

    我认为这是不可能的。

    但覆盖 __call__ 对我来说似乎是一个不错的解决方案。

    【讨论】:

      最近更新 更多