我了解为什么包含可变对象(例如tuple
)的list
不可哈希,因为元组中的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__())
为什么元组和命名元组之间存在这种差异?
最佳答案
你永远不会那样做。您使用str
,'adam'
和int
,20
创建一个命名元组
以下:
named_tuple = namedtuple("TestTuple", 'name age')
和
named_tuple = namedtuple("TestTuple", ["name", "age"])
不要而不是创建
namedtuple
对象,它们创建namedtuple
类。根据docs:换句话说,
collections.namedtuple
是一个返回类的工厂函数。如果创建这些类的实例,则它们的实例与常规tuple
实例遵循相同的规则。因此请考虑:
>>> from collections import namedtuple
>>> TestTuple = namedtuple('TestTuple', ['name', 'age'])
>>> type(TestTuple)
<class 'type'>
>>> class A: pass
...
>>> type(A)
<class 'type'>
TestTuple是
namedtuple
工厂函数的返回值,它不是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参数可以接受字段名称的序列(例如列表),或者为了方便起见,可以接受由空格/逗号分隔的字段名称字符串,因此也可以从docs中获取:
关于python - 为什么当包含可变对象的元组不包含时,包含可变对象的NamedTuple是可散列的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52920973/