为什么Python引发TypeError而不是SyntaxError?

Dan*_*man 37 python

一个纯粹出于好奇心的问题.这显然是无效的语法:

foo = {}
foo['bar': 'baz']
Run Code Online (Sandbox Code Playgroud)

很明显发生了什么,开发人员从字典定义中移出一行,但没有将它从文字字典声明更改为赋值语法(并且已经适当地模拟了结果).

但我的问题是,为什么Python会TypeError: unhashable type在这里而不是SyntaxError?它试图散列的是什么类型?这样做:

'bar': 'baz'
Run Code Online (Sandbox Code Playgroud)

是一个SyntaxError,如下所示:

['bar': 'baz']
Run Code Online (Sandbox Code Playgroud)

所以我看不出什么类型的东西是不可用的.

Ign*_*ams 62

在索引操作中使用冒号会生成一个slice不可清除对象.

  • 我不得不承认,我没有想到.+1 (3认同)

mou*_*uad 21

我只是想为Ignacio的答案添加一些细节(这很棒)并且花了我一些时间来理解,对于像我这样没有得到它的人(我可能是唯一没有得到它的人,因为我没有看到有人问我不明白,但怎么知道:)):

我第一次想知道什么片?字典索引不接受切片?

但这是我的一个愚蠢的问题,因为我忘记了python是动态的(我多么愚蠢)所以当python编译代码时,第一次python不知道是否foo是字典或列表所以它只是读取任何表达式像这个foo ['foo':'bar']作为切片,要知道你可以这样做:

def f():
    foo = {}
    foo['bar':'foo']
Run Code Online (Sandbox Code Playgroud)

通过使用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   
Run Code Online (Sandbox Code Playgroud)

在我第一次承认我没有想到这一点,我确实直接去了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;
    } 
    ....
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助像我这样的人了解Ignacio的响应,对不起,如果我只是重复Ignacio的答案:)