一个纯粹出于好奇心的问题。这显然是无效的语法:
foo = {}
foo['bar': 'baz']
显而易见的是,开发人员从字典定义中删除了一行,但没有将它从文字字典声明更改为赋值语法(并且已经适当地模拟了结果)。
但我的问题是,为什么Python在这里而不是TypeError: unhashable type
引发SyntaxError
?它试图散列的是什么类型?只是这样做:
'bar': 'baz'
是一个SyntaxError,就是这样:
['bar': 'baz']
因此我无法看到正在创建的哪种类型不可用。
答案 0 :(得分:63)
在索引操作generates a slice
object中使用冒号,该操作不可清除。
答案 1 :(得分:21)
我只是想向Ignacio answer添加一些细节(这很棒),这需要我一些时间来理解,对于像我这样没有得到它的人(我可能是唯一一个没有得到它的人)得到它,因为我没有看到有人问我不明白但是怎么知道:)):
我第一次想知道什么切片?字典索引不接受切片?
但这是我的一个愚蠢的问题,因为我忘记了python是动态的(我多么愚蠢)所以当python编译代码时,第一次python不知道foo
是否是字典或一个列表,所以它只是读取任何像这个foo ['foo':'bar']的表达式作为切片,知道你可以这样做:
def f():
foo = {}
foo['bar':'foo']
并使用dis模块,您会看到表达式'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;
}
....
希望这可以帮助像我一样的人理解伊格纳西奥的伟大反应,如果我只是重复伊格纳西奥的回答,我很抱歉:)