为什么包含可变对象的 NamedTuple 可哈希,而包含可变对象的 Tuple 不可哈希?
Why is a NamedTuple containing mutable objects hashable, when a Tuple containing mutable objects is not?
我理解为什么包含像 list
这样的可变对象的 tuple
不可哈希,因为元组中的 list
项仍然可以更新。
示例:
# hashable
tuple_test = (1,2,3)
print(tuple_test.__hash__())
虽然这是不可哈希的:
# Not hashable
tuple_test2 = (1,2, [1,2])
print(tuple_test2.__hash__())
以上内容对我来说很有意义。
但是当我用 list
个项目创建一个 namedtuple
时,它仍然是可哈希的:
# hashable
named_tuple = namedtuple("TestTuple", 'name age')
当我添加 list
:
# still hashable
named_tuple = namedtuple("TestTuple", ["name", "age"])
print(named_tuple(name="adam", age=20).__hash__())
为什么元组和命名元组之间存在这种差异?
But when I create a namedtuple with list as items it is still
hashable...
你永远不会那样做。您使用 str
、'adam'
和 int
、20
创建命名元组
以下:
named_tuple = namedtuple("TestTuple", 'name age')
和
named_tuple = namedtuple("TestTuple", ["name", "age"])
不创建namedtuple
对象,它们创建namedtuple
classes。根据 docs:
Returns a new tuple subclass named typename.
换句话说,collections.namedtuple
是一个return是class的工厂函数。如果您创建这些 class 的实例,它们的实例将遵循与常规 tuple
实例相同的规则。
所以考虑:
>>> from collections import namedtuple
>>> TestTuple = namedtuple('TestTuple', ['name', 'age'])
>>> type(TestTuple)
<class 'type'>
>>> class A: pass
...
>>> type(A)
<class 'type'>
TestTuple,namedtuple
工厂函数的return值,不是namedtuple实例,它是type
的实例,像所有其他 classes.
当您创建此 class 的实例时:
>>> 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 参数接受字段名序列(例如列表),或者为方便起见,space/comma-delimited 字段名字符串,因此也来自文档:
...
The field_names are a sequence of strings such as ['x', 'y'].
Alternatively, field_names can be a single string with each fieldname
separated by whitespace and/or commas, for example 'x y' or 'x, y'.
我理解为什么包含像 list
这样的可变对象的 tuple
不可哈希,因为元组中的 list
项仍然可以更新。
示例:
# hashable
tuple_test = (1,2,3)
print(tuple_test.__hash__())
虽然这是不可哈希的:
# Not hashable
tuple_test2 = (1,2, [1,2])
print(tuple_test2.__hash__())
以上内容对我来说很有意义。
但是当我用 list
个项目创建一个 namedtuple
时,它仍然是可哈希的:
# hashable
named_tuple = namedtuple("TestTuple", 'name age')
当我添加 list
:
# still hashable
named_tuple = namedtuple("TestTuple", ["name", "age"])
print(named_tuple(name="adam", age=20).__hash__())
为什么元组和命名元组之间存在这种差异?
But when I create a namedtuple with list as items it is still hashable...
你永远不会那样做。您使用 str
、'adam'
和 int
、20
以下:
named_tuple = namedtuple("TestTuple", 'name age')
和
named_tuple = namedtuple("TestTuple", ["name", "age"])
不创建namedtuple
对象,它们创建namedtuple
classes。根据 docs:
Returns a new tuple subclass named typename.
换句话说,collections.namedtuple
是一个return是class的工厂函数。如果您创建这些 class 的实例,它们的实例将遵循与常规 tuple
实例相同的规则。
所以考虑:
>>> from collections import namedtuple
>>> TestTuple = namedtuple('TestTuple', ['name', 'age'])
>>> type(TestTuple)
<class 'type'>
>>> class A: pass
...
>>> type(A)
<class 'type'>
TestTuple,namedtuple
工厂函数的return值,不是namedtuple实例,它是type
的实例,像所有其他 classes.
当您创建此 class 的实例时:
>>> 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 参数接受字段名序列(例如列表),或者为方便起见,space/comma-delimited 字段名字符串,因此也来自文档:
... The field_names are a sequence of strings such as ['x', 'y']. Alternatively, field_names can be a single string with each fieldname separated by whitespace and/or commas, for example 'x y' or 'x, y'.