关于可排列对象的解释所需的解释 [英] Explanation needed regarding explanation of hashable objects

查看:158
本文介绍了关于可排列对象的解释所需的解释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Mark Ransom 有关散列的SO问题在这里:


[...]如果
对象的哈希值
生命期内永远不会更改
,则
对象是可哈希的。所以根据官方的定义,即使有$ __ hash __()函数,任何可变值都不能
可哈希值。我的声明
关于这两项要求是必要的,这是不真实的,因为
可以哈希已经暗示要求是不可变的。


我想确认一下,我说得对 - 即使不是母语的人 - 所以我希望有人纠正我,如果我错了。



假设这class

  class作者(object):
def __init __(self,id,name,age):
self.id = id
self.name = name
self.age = age

def __eq __(self,other):
返回self.id == other.id\
和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 中的对象是不可散列的,因此例如在dictionarys中不可用作键。我看起来是对的还是看起来,我需要更多的解释? : - )

解决方案

如果您承诺永不重置 id name 。你不能保证这些属性永远不会被重置,这是因为Python原理我们都同意这里的成年人,但提供重置 __ hash __ 依赖的属性的方法将是非常糟糕的风格。



例如,如果您为 Author 的实例提供了 set_name 方法,但没有 set_id ,那么该类的客户端可以合理地假设 __ hash __ 仅运行 id



如果您想让 Author的客户清楚他们不应该重置某个属性,您可以通过在其名称前加一个 _ 来将其标记为私有。如果您仍希望使用通用名称提供(只读)访问属性,则可以将其设置为属性

  class作者(object):
def __init __(self,身份证,姓名,年龄):
self._id = id
self._name =姓名
self.age =年龄#年龄往往会改变,因此可变

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

def __eq __(self,other):
返回self.id == other.id\
和self.name == other.name

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


Mark Ransom answered on a SO question about hashes here in SO:

[...] An object is hashable if it has a hash value which never changes during its lifetime. So by the official definition, anything mutable can't be hashable, even if it has a __hash__() function. My statement about both requirements being necessary is untrue, because being hashable already implies the requirement to be immutable.

I want to make sure, that I got that right - even as a non native speaker - so I hope someone corrects me if I got it wrong.

Assuming this class

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))

I understand, that __eq__ allows me to compare objects of this class with the == operator. From Marks answer I understand, that even if my object peter = Author(1, "Peter", 33) has a __hash__ it is not hashable because I potentially could do something like peter.age = 43 which means it is not immutable. So my objects of the class Author are not hashable and therefore not usable as keys in dictionarys for example? Did I get right or does it seem, that I need more explanation? :-)

解决方案

Instances of this class are hashable if you promise never to reset id or name on them. You can't guarantee that these attributes will never be reset, by the Python principle that "we are all consenting adults here", but it would be very bad style to offer methods that reset the attributes that __hash__ relies on.

E.g., if you offer a set_name method on instances of Author, but no set_id, then clients of the class can reasonably presume that __hash__ operates only on the id.

If you want to make it clear to clients of Author that they should not reset some attribute, you can label it private by prepending an _ to its name. If you then still want to offer (read-only) access to the attribute using its common name, you can make it a 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))

这篇关于关于可排列对象的解释所需的解释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆