Why does Python raise TypeError rather than SyntaxError?

前端 未结 2 1675
一个人的身影
一个人的身影 2020-12-30 18:59

A question purely for curiosity\'s sake. This is obviously invalid syntax:

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

It\'s obvious what happened, the

相关标签:
2条回答
  • 2020-12-30 19:37

    Using the colon in an indexing operation generates a slice object, which is not hashable.

    0 讨论(0)
  • 2020-12-30 19:37

    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:

    def f():
        foo = {}
        foo['bar':'foo']
    

    and by using dis module you will see that the expression 'bar':'foo' has been automatically convert to a slice:

    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   
    

    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 raise unhashable type, so here is the code of dictionary __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;
        } 
        ....
    

    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 :)

    0 讨论(0)
提交回复
热议问题