我有两个用户定义的对象,比如说a
和b
.
这两个对象都具有相同的hash
值.
然而,id(a)
并且id(b)
是不平等的.
此外,
>>> a is b False >>> a == b True
从这个观察中,我可以推断出以下情况吗?
不相等的对象可能具有相同的hash
值.
等于对象需要具有相同的id
值.
无论何时obj1 is obj2
调用,id
都会比较两个对象的值,而不是它们的hash
值.
Blckknght.. 34
有三个概念,试图理解的时候把握id
,hash
以及==
和is
运营商:身份,价值和哈希值.并非所有对象都有三个.
所有对象都有一个标识,尽管在某些情况下甚至可能会有点滑.该id
函数返回一个对应于对象标识的数字(在cpython中,它返回对象的内存地址,但其他解释器可能返回其他内容).如果两个对象(同时存在)具有相同的标识,则它们实际上是对同一对象的两个引用.该is
运营商的身份进行比较的项目,a is b
相当于id(a) == id(b)
.
当您处理在其实现中某处缓存的对象时,身份可能会有点混乱.例如,cpython中的小整数和字符串的对象在每次使用时都不会重新生成.相反,现有对象会在需要时返回.您不应该在代码中依赖于此,因为它是cpython的实现细节(其他解释器可能以不同方式执行或根本不执行).
所有对象也有一个值,虽然这有点复杂.某些对象除了其标识之外没有其他有意义的值(因此,在某些情况下,标识可能是同义的).值可以定义为==
运算符比较的值,因此任何时候a == b
,您都可以说a
并且b
具有相同的值.容器对象(如列表)具有由其内容定义的值,而其他一些对象将具有基于其属性的值.不同类型的对象有时可以具有相同的值,如数字:( 由于历史原因,0 == 0.0 == 0j == decimal.Decimal("0") == fractions.Fraction(0) == False
是的,bool
s是Python中的数字).
如果类没有定义__eq__
方法(实现==
运算符),它将继承默认版本,object
并且它的实例将仅通过它们的标识进行比较.当其他相同的实例可能具有重要的语义差异时,这是适当的.例如,连接到同一主机的同一端口的两个不同的套接字需要区别对待,如果一个是获取HTML网页而另一个是获取从该页面链接的图像,因此它们没有相同的值.
除了值之外,一些对象具有哈希值,这意味着它们可以用作字典键(并存储在set
s中).该函数hash(a)
返回对象a
的哈希值,这是一个基于对象值的数字.对象的哈希值必须在对象的生命周期内保持不变,因此只有当一个对象的值是不可变的时(或者因为它基于对象的标识,或者因为它基于对象的内容),它才有可能是可清除的.对象本身是不可变的).
多个不同的对象可能具有相同的哈希值,但设计良好的哈希函数将尽可能避免这种情况.在字典中存储具有相同散列的对象比存储具有不同散列的对象的效率低得多(每个散列冲突需要更多工作).默认情况下,对象是可清除的(因为它们的默认值是它们的标识,它是不可变的).如果__eq__
在自定义类中编写方法,Python将禁用此默认哈希实现,因为您的__eq__
函数将为其实例定义值的新含义.__hash__
如果你希望你的类仍然可以清洗,你还需要编写一个方法.如果您从hashable类继承但不希望自己是hasable,则可以__hash__ = None
在类体中设置.
Alex Riley.. 6
不等的对象可能具有相同的哈希值.
是的,这是真的.一个简单的例子是hash(-1) == hash(-2)
在CPython中.
等于对象需要具有相同的id值.
一般来说,这不是假的.@chepner注意到的一个简单的例子是,5 == 5.0
但是id(5) != id(5.0)
.
无论何时
obj1 is obj2
调用,都会比较两个对象的id值,而不是它们的哈希值.
是的,这是真的.is
比较id
对象的相等性(在CPython中它是对象的内存地址).通常,这与对象的哈希值无关(对象甚至不需要可哈希).
有三个概念,试图理解的时候把握id
,hash
以及==
和is
运营商:身份,价值和哈希值.并非所有对象都有三个.
所有对象都有一个标识,尽管在某些情况下甚至可能会有点滑.该id
函数返回一个对应于对象标识的数字(在cpython中,它返回对象的内存地址,但其他解释器可能返回其他内容).如果两个对象(同时存在)具有相同的标识,则它们实际上是对同一对象的两个引用.该is
运营商的身份进行比较的项目,a is b
相当于id(a) == id(b)
.
当您处理在其实现中某处缓存的对象时,身份可能会有点混乱.例如,cpython中的小整数和字符串的对象在每次使用时都不会重新生成.相反,现有对象会在需要时返回.您不应该在代码中依赖于此,因为它是cpython的实现细节(其他解释器可能以不同方式执行或根本不执行).
所有对象也有一个值,虽然这有点复杂.某些对象除了其标识之外没有其他有意义的值(因此,在某些情况下,标识可能是同义的).值可以定义为==
运算符比较的值,因此任何时候a == b
,您都可以说a
并且b
具有相同的值.容器对象(如列表)具有由其内容定义的值,而其他一些对象将具有基于其属性的值.不同类型的对象有时可以具有相同的值,如数字:( 由于历史原因,0 == 0.0 == 0j == decimal.Decimal("0") == fractions.Fraction(0) == False
是的,bool
s是Python中的数字).
如果类没有定义__eq__
方法(实现==
运算符),它将继承默认版本,object
并且它的实例将仅通过它们的标识进行比较.当其他相同的实例可能具有重要的语义差异时,这是适当的.例如,连接到同一主机的同一端口的两个不同的套接字需要区别对待,如果一个是获取HTML网页而另一个是获取从该页面链接的图像,因此它们没有相同的值.
除了值之外,一些对象具有哈希值,这意味着它们可以用作字典键(并存储在set
s中).该函数hash(a)
返回对象a
的哈希值,这是一个基于对象值的数字.对象的哈希值必须在对象的生命周期内保持不变,因此只有当一个对象的值是不可变的时(或者因为它基于对象的标识,或者因为它基于对象的内容),它才有可能是可清除的.对象本身是不可变的).
多个不同的对象可能具有相同的哈希值,但设计良好的哈希函数将尽可能避免这种情况.在字典中存储具有相同散列的对象比存储具有不同散列的对象的效率低得多(每个散列冲突需要更多工作).默认情况下,对象是可清除的(因为它们的默认值是它们的标识,它是不可变的).如果__eq__
在自定义类中编写方法,Python将禁用此默认哈希实现,因为您的__eq__
函数将为其实例定义值的新含义.__hash__
如果你希望你的类仍然可以清洗,你还需要编写一个方法.如果您从hashable类继承但不希望自己是hasable,则可以__hash__ = None
在类体中设置.
不等的对象可能具有相同的哈希值.
是的,这是真的.一个简单的例子是hash(-1) == hash(-2)
在CPython中.
等于对象需要具有相同的id值.
一般来说,这不是假的.@chepner注意到的一个简单的例子是,5 == 5.0
但是id(5) != id(5.0)
.
无论何时
obj1 is obj2
调用,都会比较两个对象的id值,而不是它们的哈希值.
是的,这是真的.is
比较id
对象的相等性(在CPython中它是对象的内存地址).通常,这与对象的哈希值无关(对象甚至不需要可哈希).