Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test equality of two functions in python

I want to make two functions equal to each other, like this:


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

How should I do it? I know I could probably override eq and ne if fa, fb, fc are instances of some class. But here eq is not in dir(fa) and adding it the list doesnt work. I figured out some workaround like using a cache, e.g.,


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 = {}

By this way there is a guarantee that there is only one function for the same signature value (kinda like a singleton). But I am really looking for some neater solutions.

like image 683
dolaameng Avatar asked Feb 20 '23 08:02

dolaameng


2 Answers

If you turned your functions into instances of some class that overrides __call__() as well as the comparison operators, it will be very easy to achieve the semantics you want.

like image 51
NPE Avatar answered Feb 25 '23 17:02

NPE


It is not possible to override the __eq__ implementation for functions (tested with 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'
like image 42
schlamar Avatar answered Feb 25 '23 17:02

schlamar