简体   繁体   中英

Why does Python raise TypeError rather than SyntaxError?

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

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

It's obvious what happened, the developer moved a line out of the dictionary definition but didn't change it from the literal dictionary declaration to the assignment syntax (and has been suitably mocked as a result).

But my question is, why does Python raise TypeError: unhashable type here rather than SyntaxError ? What type is it attempting to hash? Just doing this:

'bar': 'baz'

is a SyntaxError, as is this:

['bar': 'baz']

so I can't see what type is being created that is unhashable.

在索引操作中使用冒号会生成slice对象 ,该对象不可清除。

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM