Mark Ransom在SO中的SO question about hashes上回答:



我想确定的是,我是正确的-即使是非母语人士-所以我希望有人能纠正我的想法,如果我做错了。

假设这个类

class Author(object):
    def __init__(self, id, name, age):
        self.id = id
        self.name = name
        self.age = age

    def __eq__(self, other):
        return self.id==other.id\
               and self.name==other.name

    def __hash__(self):
        return hash(('id', self.id,
                     'name', self.name))

我知道,__eq__允许我将此类的对象与==运算符进行比较。从Marks答案中,我了解到,即使我的对象peter = Author(1, "Peter", 33)具有__hash__,它也不是可哈希的,因为我可能会做类似peter.age = 43的操作,这意味着它不是不变的。因此,我的Author类的对象不可哈希,因此不能用作例如字典中的键?我是对的还是看来我需要更多的解释? :-)

最佳答案

如果您保证绝不会在其实例上重置idname,则此类的实例是可哈希的。您无法保证使用"we are all consenting adults here"的Python原则永远不会重置这些属性,但是提供重置__hash__所依赖的属性的方法将是非常糟糕的样式。

例如,如果您在set_name实例上提供Author方法,但没有set_id,则该类的客户端可以合理地假设__hash__id上仅操作。

如果要向Author的客户明确表明他们不应重置某些属性,则可以通过在其名称前添加_来将其标记为私有(private)。然后,如果您仍想使用其公共(public)名称提供(只读)属性访问权限,则可以将其设置为property:

class Author(object):
    def __init__(self, id, name, age):
        self._id = id
        self._name = name
        self.age = age      # ages tend to change, so mutable

    id = property(lambda self: self._id)
    name = property(lambda self: self._name)

    def __eq__(self, other):
        return self.id==other.id\
               and self.name==other.name

    def __hash__(self):
        return hash(('id', self.id,
                     'name', self.name))

关于python - 关于可散列对象的说明需要说明,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6652878/

10-12 20:25
查看更多