gpt4 book ai didi

Python set().issubset() 没有按预期工作

转载 作者:太空狗 更新时间:2023-10-30 00:45:59 26 4
gpt4 key购买 nike

我正在尝试使用 set().issubset() 来比较序列。正如您所想象的,它没有按预期工作 ;) 提前:对于长代码块感到抱歉。

class T(object):
def __init__(self, value, attributes = None):
self.value = value
self.attributes = Attributes(attributes)

def __eq__(self, other):
if not isinstance(other, T):
return False
if self.value == other.value and self.attributes == other.attributes:
return True
else:
return False

def __ne__(self, other):
if not isinstance(other, T):
return True
if self.value != other.value or self.attributes != other.attributes:
return True
else:
return False

class Attributes(dict):
def __init__(self, attributes):
super(dict, self)
self.update(attributes or dict())

def __eq__(self, other):
if self.items() == other.items():
return True
else:
return False

def __ne__(self, other):
if not self.items() == other.items():
return True
else:
return False

def __cmp__(self, other):
return self.items().__cmp__(other.items())


x = [T("I", {'pos': 0}), T("am", {'pos': 1}), T("a", {'pos': 2}), T("test", {'pos': 3})]
y = [T("a", {'pos': 2}), T("test", {'pos': 3})]
xx = set(x)
yy = set(y)

assert y[0] == x[2], "__eq__ did fail, really?" #works
assert y[1] == x[3], "__eq__ did fail, really?" #works
assert xx-(yy-xx) == xx, "set subtract not working" #works, but is nonsense. see accepted answer
assert not xx.issubset(yy), "i am doing it wrong..." #works
assert yy.issubset(xx), "issubset not working :(" #FAILS!

运行上面的代码使最后一个断言失败:

$ python
Python 2.7.2 (v2.7.2:8527427914a2, Jun 11 2011, 15:22:34)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import issubsettest
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "issubsettest.py", line 52, in <module>
assert yy.issubset(xx), "issubset not working :("
AssertionError: issubset not working :(
>>>

我在这里错过了什么?

最佳答案

您的对象正在按它们的 id 进行哈希处理(您没有覆盖 __hash__)。当然,它们不是子集,因为 xxyy 包含唯一对象。

为此,您需要想出某种__hash__ 函数。 __hash__ 应该始终为对象返回相同的值,这就是为什么通常理解您不会改变可散列对象的原因。例如,一个选择可能是:

class T(object):
#<snip> ...

def __hash__(self):
return hash(self.value)

#... </snip>

理解 self.value 在对象的生命周期内不能改变。 (请注意,我并不是说这是一个好的选择。您使用的实际哈希实际上取决于您的实际应用)


现在是为什么——集合(和指令)背后的魔力和惊人的性能是它们依赖于散列。基本上,每个可散列对象都变成了一个“唯一”(在完美世界中)的数字。 Python 采用该“唯一”数字并将其转换为数组索引,它可以使用该索引来获取对象的句柄(这里的魔法有点难以解释,但对于本次讨论而言并不重要)。因此,不是通过将对象与“数组”(通常称为表)中的所有其他对象进行比较来查找对象——这是一种昂贵的操作,它根据散列值确切地知道在哪里寻找对象(便宜) .默认情况下,用户定义的对象通过它们的 id(内存地址)散列。当您创建集合 xx 时,python 会查看每个对象 id 并根据它们的 id 将它们放入 a 中。现在当你执行 xx.issubset(yy) 时,python 会查看 xx 中的所有 id,并检查它们是否都在 yy 中>。但是它们都不在 yy 中,因为它们都是唯一的对象(因此具有唯一的哈希值)。

但是你说,“为什么 xx-(yy-xx) == xx 有效?”好问题。让我们把它分开。

首先,我们有(yy - xx)。这将返回一个空集,因为 xx 中的元素也不在 yy 中(它们都散列为不同的值,因为它们都有唯一的 id)。所以你真的在做

xx - set([]) == xx

为什么这是 True 应该很明显。

关于Python set().issubset() 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12979703/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com