为什么在包含可变对象的元组不是的情况下,包含可变对象的NamedTuple是可哈希的?

时间:2018-10-22 00:04:14

标签: python namedtuple

我了解为什么包含nuts['Price'] = nuts['Type'].map(pricedf['Type']) 之类的可变对象的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

为什么元组和namedtuple之间有这种区别?

1 个答案:

答案 0 :(得分:6)

  

但是当我创建一个带有列表作为项目的namedtuple时,它仍然   可哈希的...

您永远不会那样做。您创建一个具有str'adam'int20

的命名元组

以下内容:

named_tuple = namedtuple("TestTuple", 'name age')

named_tuple = namedtuple("TestTuple", ["name", "age"])

创建namedtuple对象,它们创建namedtuple 。根据{{​​3}}:

  

返回一个名为typename的新元组子类。

换句话说,collections.namedtuple是一个工厂函数,它返回一个 class 。如果创建这些类的实例,则它们的实例与常规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参数可以接受字段名的序列(例如列表),或者为了方便起见,可以接受由空格/逗号分隔的字段名字符串,因此也可以从文档中获取:

  

...   field_names是一系列字符串,例如['x','y']。   另外,field_names可以是单个字符串,每个fieldname   用空格和/或逗号分隔,例如“ x y”或“ x,y”。