- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
SO 上的一个常见问题是 removing duplicates from a list of lists .由于列表是不可散列的,set([[1, 2], [3, 4], [1, 2]])
抛出 TypeError: unhashable type: 'list'
.这类问题的答案通常涉及使用元组,它们是不可变的,因此是可散列的。
这个对 What makes lists unhashable? 的回答包括以下内容:
If the hash value changes after it gets stored at a particular slot in the dictionary, it will lead to an inconsistent dictionary. For example, initially the list would have gotten stored at location A, which was determined based on the hash value. If the hash value changes, and if we look for the list we might not find it at location A, or as per the new hash value, we might find some other object.
但我不太明白,因为可以毫无问题地更改可用于字典键的其他类型:
>>> d = {}
>>> a = 1234
>>> d[a] = 'foo'
>>> a += 1
>>> d[a] = 'bar'
>>> d
{1234: 'foo', 1235: 'bar'}
很明显,如果a
的值发生变化,它会散列到字典中的不同位置。 为什么相同的假设对列表来说是危险的?为什么下面的散列列表方法是不安全的,因为无论如何我们都会在需要时使用它?
>>> class my_list(list):
... def __hash__(self):
... return tuple(self).__hash__()
...
>>> a = my_list([1, 2])
>>> b = my_list([3, 4])
>>> c = my_list([1, 2])
>>> foo = [a, b, c]
>>> foo
[[1, 2], [3, 4], [1, 2]]
>>> set(foo)
set([[1, 2], [3, 4]])
这似乎解决了 set()
问题,为什么这是一个问题?列表可能是可变的,但它们是有序的,这似乎是散列所需的全部内容。
最佳答案
您似乎混淆了可变性和重新绑定(bind)。 a += 1
将一个新对象,即数值为 1235 的 int
对象分配给 a
。在底层,对于像 int
这样的不可变对象(immutable对象),a += 1
与 a = a + 1
是一样的。
原始的 1234
对象没有发生变化。该字典仍然使用一个 int
对象,其数值为 1234 作为键。字典仍然保留对该对象的引用,即使a
现在引用了不同的对象。这两个引用是独立的。
试试这个:
>>> class BadKey:
... def __init__(self, value):
... self.value = value
... def __eq__(self, other):
... return other == self.value
... def __hash__(self):
... return hash(self.value)
... def __repr__(self):
... return 'BadKey({!r})'.format(self.value)
...
>>> badkey = BadKey('foo')
>>> d = {badkey: 42}
>>> badkey.value = 'bar'
>>> print(d)
{BadKey('bar'): 42}
请注意,我更改了 badkey
实例上的属性 value
。我什至没有碰字典。字典反射(reflect)变化; 实际键值本身发生了变异,即名称 badkey
和字典引用的对象。
但是,您现在无法再访问该 key :
>>> badkey in d
False
>>> BadKey('bar') in d
False
>>> for key in d:
... print(key, key in d)
...
BadKey('bar') False
我已经彻底破解了我的字典,因为我无法再可靠地找到 key 。
那是因为BadKey
违反了hashability的原则;哈希值必须保持稳定。只有当您不更改散列所基于的对象的任何内容时,您才能这样做。并且哈希必须基于使两个实例相等的任何因素。
对于列表,内容 使两个列表对象相等。而且您可以更改它们,因此您也无法生成稳定的哈希值。
关于python - 为什么要使列表不可散列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39104841/
我正在尝试将抓取的 xml 输出写入 json。由于项目不可序列化,抓取失败。 从这个问题来看,它建议您需要构建一个管道,未提供的答案超出了问题 SO scrapy serializer 的范围。 所
有没有一种方法可以通过重载函数来区分参数是在编译时可评估还是仅在运行时可评估? 假设我有以下功能: std::string lookup(int x) { return table::va
我正在使用 MVVM 模式编写一个应用程序。我通过将 View 的 DataContext 属性设置为 ViewModel 的实例来向 View 提供数据。一般来说,我只是从那里使用 Binding
对于一个项目,我正在使用带有简单 python module 的传感器收集多个红外命令。 . 我收到如下字节字符串: commando1= b'7g4770CQfwCTVT9bQDAzVEBMagGR
我有一个计算方法,可以在用户使用 Cartridge 作为我的商店框架结账时计算税费。 税 = 税 * 小数(str(settings.SHOP_DEFAULT_TAX_RATE)) 计算工作正常。然
我正在用 pygame 制作一个绘图程序,我想在其中为用户提供一个选项来保存程序的确切状态,然后在稍后重新加载它。在这一点上,我保存了我的全局字典的副本,然后遍历, pickle 每个对象。 pyga
在 C++11 之前,我可以使用它来使类不可复制: private: MyClass(const MyClass&); MyClass& operator=(const MyClass&); 使用 C
大家好 :) 我在我的 VC++ 项目中使用 1.5.4-all (2014-10-22)(适用于 x86 平台的 Microsoft Visual C++ 编译器 18.00.21005.1)。 我
我有一个 python 文件:analysis.py: def svm_analyze_AHE(file_name): # obtain abp file testdata = pd.
这个问题已经有答案了: How to serialize SqlAlchemy result to JSON? (37 个回答) 已关闭 4 年前。 我正在编写小查询来从 mysql 获取数据数据库,
我是 Python 初学者,我在 JSON 方面遇到了一些问题。在我正在使用的教程中有两个函数: def read_json(filename): data = [] if os.pa
我目前正在开发一个针对 iPad 的基于 HTML5 Canvas/JavaScript 的小型绘图应用程序。它在 Safari 中运行。到目前为止,除了一件事之外,一切都进展顺利。 如果我旋转设备,
以下代码无法使用 Visual Studio 2013 编译: #include struct X { X() = default; X(const X&) = delete;
嗨,我制作了一个文本分类分类器,我在其中使用了它,它返回一个数组,我想返回 jsonresponse,但最后一行代码给我错误 'array(['cycling'], dtype =object) 不可
我使用 Flask 和 Flask-Login 进行用户身份验证。 Flask-Sqlalchemy 将这些模型存储在 sqlite 数据库中: ROLE_USER = 0 ROLE_ADMIN =
如果您尝试发送不可 JSON 序列化的对象(列表、字典、整数等以外的任何对象),您会收到以下错误消息: "errorMessage": "Object of type set is not JSON
我在尝试 move std::vector 时遇到崩溃其中 T显然是不可 move 的(没有定义 move 构造函数/赋值运算符,它包含内部指针) 但为什么 vector 的 move 函数要调用 T
我尝试在用户成功登录后将 token 返回给他们,但不断收到以下错误: 类型错误:“字节”类型的对象不可 JSON 序列化 我该如何解决这个问题?这是我到目前为止的代码: if user:
我是一名优秀的程序员,十分优秀!