为什么 foo['bar': 'baz'] 引发 TypeError 而不是 SyntaxError?
纯粹出于好奇而提出的问题。这显然是无效的语法:
foo = {}
foo['bar': 'baz']
很明显发生了什么,开发人员从字典定义中移出了一行,但没有将其从字面字典声明更改为赋值语法(因此已被适当地模拟)。
但我的问题是,为什么Python在这里引发TypeError: unhashable type
而不是SyntaxError
?它尝试散列什么类型?只是这样做:
'bar': 'baz'
是一个SyntaxError
,就像这样:
['bar': 'baz']
所以我看不到正在创建的不可散列的类型。
A question purely for curiosity's sake. This is obviously invalid syntax:
foo = {}
foo['bar': 'baz']
It's obvious what happened, the developer moved a line out of the dictionary definition but didn't change it from the literal dictionary declaration to the assignment syntax (and has been suitably mocked as a result).
But my question is, why does Python raise TypeError: unhashable type
here rather than SyntaxError
? What type is it attempting to hash? Just doing this:
'bar': 'baz'
is a SyntaxError
, as is this:
['bar': 'baz']
so I can't see what type is being created that is unhashable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在索引操作中使用冒号生成一个
slice
对象,不可散列。Using the colon in an indexing operation generates a
slice
object, which is not hashable.我只想在 Ignacio 答案(这很棒)这需要我一些时间来理解,对于像我这样没有得到它的人(我可能是唯一一个没有得到它的人,因为我没有看到有人问我没有)不明白,但怎么知道:) ) :
第一次我想知道什么切片?字典索引不接受切片?
但这是我的一个愚蠢的问题,因为我忘记了 python 是动态的(我是多么愚蠢)所以当 python 第一次编译代码时 python 不知道是否
foo
是一个字典或列表,因此它只是将 foo['foo':'bar'] 这样的任何表达式读取为切片,知道您可以这样做:并使用 dis 模块你会看到表达式
'bar':'foo'
已经自动转换为切片:我第一次承认我没有考虑到这一点,我确实直接进入了python的源代码试图理解为什么,因为list的
__getitems__
不像字典的__getitem__
但现在我明白了为什么,因为如果它的切片和切片是不可散列的,它应该引发unhashable 类型
,所以这里是字典的代码__getitem__
:希望这可以帮助像我这样的人理解伊格纳西奥的伟大回应,如果我只是重复伊格纳西奥的答案,抱歉:)
I just want to add some detail to Ignacio answer (which is great) and that take me some time to understand and for people like me that didn't get it (i may be the only one that didn't get it because i didn't see anyone asking i didn't understand but how knows :) ) :
the first time i wonder what slice ? dictionary indexing don't accept slicing ?
but this is a stupid question from my part because i forget that python is dynamic (how stupid i'm ) so when python compile the code the fist time python don't know if
foo
is a dictionary or a list so it just read any expression like this foo['foo':'bar'] as a slice , to know that you can just do:and by using dis module you will see that the expression
'bar':'foo'
has been automatically convert to a slice:in the first time i admit i didn't think about this and i did go directly to the source code of python trying to understand why, because the
__getitems__
of list is not like__getitem__
of a dictionary but now i understand why because if it a slice and slice are unhashable it should raiseunhashable type
, so here is the code of dictionary__getitem__
:Hope this can help some people like me to understand the great response of Ignacio, and sorry if i just duplicate the answer of Ignacio :)
表达式 foo[a:b] 是 foo[slice(a, b)] 的语法糖。也就是说,您使用
slice
对象。无论 foo 是什么,都是如此。在 Python 3.11 及更低版本中,这会引发
TypeError
,因为切片对象不是 可哈希。但是,自 Python 3.12 起(2023 年发布 - 10-02),切片对象现在是可散列的1,使其用作字典键有效。原始问题中的代码现在将引发
KeyError
而不是TypeError
:现在也可以编写
生成字典
{slice('bar', 'baz',无):1}
。1 前提是
start
、stop
和step
都是可哈希的。The expression
foo[a:b]
is syntactic sugar forfoo[slice(a, b)]
. That is, you're indexing the dictionary with aslice
object. This is true regardless of whatfoo
is.In Python 3.11 and below, this raised a
TypeError
because slice objects were not hashable. However, as of Python 3.12 (released 2023-10-02), slice objects are now hashable1, making their use as dictionary keys valid.The code in the original question will now raise a
KeyError
instead of aTypeError
:It's now also possible to write
which produces the dictionary
{slice('bar', 'baz', None): 1}
.1 Provided that
start
,stop
, andstep
are all hashable.