python - 为什么包含可变对象的 NamedTuple 是可散列的,而包含可变对象的 Tuple 不是?
问题描述
我理解为什么tuple
包含可变对象的 alist
是不可散列的,因为list
元组中的项目仍然可以更新。
例子:
# hashable
tuple_test = (1,2,3)
print(tuple_test.__hash__())
虽然这不是可散列的:
# Not hashable
tuple_test2 = (1,2, [1,2])
print(tuple_test2.__hash__())
以上对我来说很有意义。
但是当我创建一个namedtuple
带有list
项目时它仍然是可散列的:
# hashable
named_tuple = namedtuple("TestTuple", 'name age')
当我添加一个list
:
# still hashable
named_tuple = namedtuple("TestTuple", ["name", "age"])
print(named_tuple(name="adam", age=20).__hash__())
为什么元组和命名元组之间存在这种差异?
解决方案
但是当我创建一个以列表为项目的命名元组时,它仍然是可散列的......
你永远不会那样做。您使用 a和 an创建一个命名元组str
,'adam'
int
20
以下:
named_tuple = namedtuple("TestTuple", 'name age')
和
named_tuple = namedtuple("TestTuple", ["name", "age"])
不要创建对象,它们会创建类。根据文档:namedtuple
namedtuple
返回一个名为 typename 的新元组子类。
换句话说,collections.namedtuple
是一个返回类的工厂函数。如果您创建这些类的实例,它们的实例遵循与常规实例相同的规则tuple
。
所以考虑:
>>> from collections import namedtuple
>>> TestTuple = namedtuple('TestTuple', ['name', 'age'])
>>> type(TestTuple)
<class 'type'>
>>> class A: pass
...
>>> type(A)
<class 'type'>
namedtuple
工厂函数的返回值 TestTuple不是 namedtuple 实例,它是 的实例type
,就像所有其他类一样。
当您创建此类的实例时:
>>> test_tuple = TestTuple('adam',32)
>>> type(test_tuple)
<class '__main__.TestTuple'>
它们遵循常规tuple
对象所做的通常的哈希规则:
>>> hash(test_tuple)
5589201399616687819
>>> test_tuple = TestTuple('adam', [32, 31])
>>> hash(test_tuple)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
请注意, fieldnames 参数接受字段名的序列(例如列表),或者为方便起见,接受空格/逗号分隔的字段名字符串,因此也来自文档:
... field_names 是一个字符串序列,例如 ['x', 'y']。或者,field_names 可以是单个字符串,每个字段名由空格和/或逗号分隔,例如“x y”或“x, y”。
推荐阅读
- php - 如何在 laravel 中的 C:\media 等外部目录中更改媒体上传/存储文件?
- django - 访问通过表单上的 OneToOneField 模型链接的模型的数据
- java - 使用 BufferedImage 加载图像时内存使用率高
- python - 将数据附加到 json 中的 Python 函数
- r - 无论来自 R 库 rWBclimate 的内容如何,我都会收到相同的错误
- r - 在 R markdown 中指定自定义 powerpoint 主题
- django - 我将如何摆脱错误“经理”对象没有属性“活动”
- dynamic - 使用 istio 根据流量的错误响应将流量分流到两个版本
- c++ - 如何打印出 DECIMAL (tagDEC) 类型的值?
- r - 如何在R中双重集成一个函数