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