为什么Python引发TypeError而不是SyntaxError?
纯粹是出于好奇的缘故。 这显然是无效的语法:
foo = {} foo['bar': 'baz']
很明显,发生了什么事情,开发人员从字典定义中移出了一行,但没有将其从字典字典声明更改为赋值语法(因此已被适当地模拟)。
但是我的问题是,为什么Python在这里引发TypeError: unhashable type
而不是SyntaxError
? 它试图散列什么types? 只是这样做:
'bar': 'baz'
是一个SyntaxError,如下所示:
['bar': 'baz']
所以我不能看到什么types是不可能被创build的。
在索引操作中使用冒号会生成一个不可哈希的slice
对象 。
我只是想添加一些细节,以伊格纳西奥的答案 (这是伟大的),并花了我一些时间来理解和像我这样的人没有得到它(我可能是唯一没有得到它,因为我didn没有看到有人问我不明白,但是如何知道:)):
我第一次想知道什么切片? 字典索引不接受切片?
但这是我的一个愚蠢的问题,因为我忘记了python是dynamic的(我是多么愚蠢),所以当python编译代码的第一次的时间python不知道如果foo
是一个字典或列表,所以它只是读取任何像这样的expressionfoo ['foo':'bar']作为一个切片,要知道你可以这样做:
def f(): foo = {} foo['bar':'foo']
并通过使用dis模块,你会看到expression式'bar':'foo'
已经自动转换为一个片段:
dis.dis(f) 2 0 BUILD_MAP 0 3 STORE_FAST 0 (foo) 3 6 LOAD_FAST 0 (foo) 9 LOAD_CONST 1 ('bar') 12 LOAD_CONST 2 ('foo') 15 SLICE+3 <<<<<<<<<<<<<<<<<<<<<< HERE!!!!!! 16 POP_TOP 17 LOAD_CONST 0 (None) 20 RETURN_VALUE
在第一次我承认我没有想到这一点,我直接到Python的源代码试图理解为什么,因为__getitems__
的列表不是像__getitem__
字典,但现在我明白为什么,因为如果它切片和切片是不可能的,它应该引起unhashable type
,所以这里是字典的代码__getitem__
:
static PyObject * dict_subscript(PyDictObject *mp, register PyObject *key) { PyObject *v; long hash; PyDictEntry *ep; assert(mp->ma_table != NULL); if (!PyString_CheckExact(key) || // if check it's not a string (hash = ((PyStringObject *) key)->ob_shash) == -1) { hash = PyObject_Hash(key); // check if key (sliceobject) is hashable which is false if (hash == -1) return NULL; } ....
希望这可以帮助像我这样的人了解伊格纳西奥的巨大反应,对不起,如果我只是重复伊格纳西奥的答案:)