Python - 为什么不能对可变对象的方法进行哈希处理?

时间:2013-09-06 05:45:24

标签: python methods hash mutable

我理解可变对象can't be hashed,但为什么在可变对象的方法中也应如此,特别是考虑到它们按预期进行比较?

例如:

>>> d1, d2 = {}, {}
>>> d1.keys == d2.keys
False
>>> set([d1.keys])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'

在示例中,d1.keys本身并不是异常抱怨的dict。简单地将dict作为属性显然不是可以清除的一般条款,因为默认情况下,用户创建的类的实例都是可清除的并且具有__dict__属性。方法对象本身不会以任何有意义的方式在其生命周期内发生变化,无论其__self__组件是否可变。有没有什么方法我没有看到可变对象上的哈希方法会破坏哈希隐含的契约?

下面是我对包装器的尝试,它确保方法可以清洗,并且对常规方法对象也很好。对于通常不可用的方法,哈希值是从包含方法实现对象的元组和方法的__self__组件的id计算的。有什么理由可能会让我感到害怕?

class HashableMethod(object):
    __slots__ = ['_method', '_hashval', '__weakref__']

    def __init__(self, method):
        self._method = method

    def __getattr__(self, name):
        return getattr(self._method, name)

    def __call__(self, *args, **kwds):
        return self._method(*args, **kwds)

    def __eq__(self, other):
        return self._method == other

    def __hash__(self):
        try:
            return self._hashval
        except AttributeError: # self._hashval is not yet calculated
            pass

        meth = self._method
        try:
            hashval = self._hashval = hash(meth)
        except TypeError: # self._method is not ordinarily hashable
            obj = meth.__self__
            try:
                func = meth.__func__
            except AttributeError: # self._method is builtin
                func = getattr(type(obj), meth.__name__)
            hashval = self._hashval = hash((func, id(obj)))
        return hashval

0 个答案:

没有答案