我了解为什么包含可变对象(例如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'int20创建一个命名元组

以下:

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/

10-12 22:10