当一个集合中的对象相互匹配时会发生什么?

2024-10-02 22:28:35 发布

您现在位置:Python中文网/ 问答频道 /正文

正如标题所示,我有一个关于改变集合中的对象以使它们变得完全相同(在集合的眼中)的问题。只是好奇。你知道吗

我问这个关于Python的问题,但是如果它是可归纳的,请随意这样做。你知道吗

如果我在Python中理解正确,Setiterable将通过相等对象的哈希值来确定对象是否“相等”。所以对于对象ab这将是:

hash(a) == hash(b)

对于您创建的任何对象,您都可以根据自己的喜好覆盖standard hash function__hash__。你知道吗

假设您创建了一个哈希函数,该函数接受对象中的几个或所有对象,并将哈希的组合用作自己的哈希(例如,通过对它们进行ORing)。你知道吗

现在,如果在一个集合中有几个最初不同的对象,然后遍历该集合并更改其中的对象,使其内部对象匹配,那么该集合将发生什么变化?他们都会留在那里,还是会被踢出去,还是我们需要等到手术在片场进行?或者我们在什么地方犯了错误?你知道吗


Tags: 对象函数标题地方错误functionhashstandard
3条回答

考虑这个测试:

class A:
    def __init__(self, h):
        self.h = h

    def __hash__(self):
        return self.h

x = A(1)
y = A(2)

a = {x, y}

print x in a, y in a
print a

print "----"

x.h = 2

print x in a, y in a
print a

结果:

True True
set([<__main__.A instance at 0x10d94fd40>, <__main__.A instance at 0x10d94fd88>])
----
False True
set([<__main__.A instance at 0x10d94fd40>, <__main__.A instance at 0x10d94fd88>])

如您所见,第一个对象x仍然存在,但是in操作符报告它不存在。为什么会发生这种情况?你知道吗

据我所知,Set对象是使用哈希表实现的,哈希表通常具有如下结构:

 hash_value => list of objects with this hash value
 another_hash_value => list of objects with this hash value

当集合回答in请求时,它首先计算参数的散列值,然后尝试在相应的列表中找到它。我们的集合a最初是这样的:

  1 => [x]
  2 => [y]

现在,我们更改x的散列并询问集合是否存在对象。集合计算散列值(现在是2)试图在第二个列表中定位x,但失败了-因此False。你知道吗

为了让事情更有趣,让我们

a.add(x)
print x in a, y in a
print a

结果:

True True
set([<__main__.A instance at 0x107cbfd40>, 
     <__main__.A instance at 0x107cbfd88>, 
     <__main__.A instance at 0x107cbfd40>])

现在我们有两个相同的对象在集合中!如您所见,没有自动调整,也没有错误。Python是一种成年人的语言,它总是假定您知道自己在做什么。你知道吗

不允许以更改哈希值的方式修改集合的成员。

在Python中,只能在一个集合中存储可哈希对象。从documentation(我的重点):

An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal (except with themselves), and their hash value is their id().

如果你违反了这个合同(正如你在你的问题中所建议的那样),电视机就不能工作了,所有的赌注都输掉了。你知道吗

修改集合成员的正确方法是删除、更改和重新添加。这将像你期望的那样。你知道吗

[the set] will determine whether objects are 'equal' by equating their hashes

这不太正确。比较哈希值不能用来确定对象是否相等。它只能用于确定对象不相等。这是一个微妙但重要的区别。你知道吗

首先,^{}的元素必须是^{}

The elements of a set must be hashable.

^{}表示:

An object is hashable if it has a hash value which never changes during its lifetime [...]

所以只要你不改变对象的散列值(它的__hash__方法的结果)保持不变,一切都很好。你知道吗

在Python中,不可变对象通常被认为是可哈希的,而可变对象则不是:

All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are.

相关问题 更多 >