代码之家  ›  专栏  ›  技术社区  ›  Daniel Roseman

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

  •  37
  • Daniel Roseman  · 技术社区  · 14 年前

    纯粹出于好奇的问题。这显然是无效语法:

    foo = {}
    foo['bar': 'baz']
    

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

    'bar': 'baz'
    

    是一个语法错误,如下所示:

    ['bar': 'baz']
    

    2 回复  |  直到 14 年前
        1
  •  62
  •   Community miroxlav    7 年前

    在索引操作中使用冒号 generates a slice object ,这是不可哈希的。

        2
  •  21
  •   Community miroxlav    7 年前

    我只是想给 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 ,所以这是字典的代码 :

    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;
        } 
        ....
    

    希望这能帮助像我这样的人理解伊格纳西奥的伟大回应,如果我只是重复伊格纳西奥的回答,我会很抱歉:)