Getting a set of lambda functions

bearophileHUGS at lycos.com bearophileHUGS at lycos.com
Sun May 25 17:39:28 EDT 2008


This may have some bugs left, but it looks a bit better:

from inspect import getargspec

class HashableFunction(object):
    """Class that can be used to wrap functions, to allow their
hashing,
    for example to create a set of unique functions.

    >>> func_strings = ['x', 'x+1', 'x+2', 'x']
    >>> func_list1 = [eval('lambda x:' + func) for func in
func_strings]
    >>> func_set = set(HashableFunction(f) for f in func_list1)
    >>> len(func_set)
    3
    >>> set(f(10) for f in func_set) == set([10, 11, 12])
    True

    >>> func_list2 = [lambda x=1: x, lambda x: x]
    >>> len(set(HashableFunction(f) for f in func_list2))
    2

    >>> class Foo:
    ...   def __eq__(self, other): raise NotImplementedError
    >>> func_list3 = [lambda x=Foo(): x, lambda x=Foo(): x]
    >>> set(HashableFunction(f) for f in func_list3)
    Traceback (most recent call last):
      ...
    NotImplementedError
    """
    # Original code by I V <ivlenin at gmail.com>, 25 May 2008,
    # http://groups.google.com/group/comp.lang.python/browse_thread/thread/a973de8f3562675c
    # modified by bearophile
    def __init__(self, func):
        self._func = func
        signature = getargspec(func)
        self._hash = hash(self._func.func_code) ^ \
                     hash(tuple(signature[0]) + tuple(signature[1:3]))
    def __eq__(self, other):
        return self._func.func_code == other._func.func_code and \
               getargspec(self._func) == getargspec(other._func)
    def __hash__(self):
        return self._hash
    def __call__(self, *args, **kwargs):
        return self._func(*args, **kwargs)

I haven't put a full hashing of getargspec(self._func) too into the
__init__() because it may contain too much nested unhashable
structures, but the __eq__() is able to tell them apart anyway, with
some collisions.

Bye,
bearophile



More information about the Python-list mailing list