¿Por qué Python genera TypeError en lugar de SyntaxError?

Una pregunta puramente por el bien de la curiosidad. Obviamente, esta syntax no es válida:

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

Es obvio lo que sucedió, el desarrollador movió una línea fuera de la definición del diccionario pero no la cambió de la statement literal del diccionario a la syntax de la asignación (y como resultado se ha burlado adecuadamente).

Pero mi pregunta es, ¿por qué Python TypeError: unhashable type aquí en lugar de SyntaxError ? ¿Qué tipo está intentando hacer hash? Solo haciendo esto:

 'bar': 'baz' 

es un SyntaxError, como es esto:

 ['bar': 'baz'] 

así que no puedo ver qué tipo de creación se está creando.

El uso de los dos puntos en una operación de indexación genera un objeto de sector , que no es hashable.

Solo quiero agregar algunos detalles a la respuesta de Ignacio (que es genial) y eso me tomó un tiempo para entender y para las personas como yo que no lo entendieron (puede que sea el único que no lo haya entendido porque no lo hice). No veo a nadie preguntando que no entendí, pero cómo lo sabe :)):

la primera vez me pregunto que rebanada? Diccionario de indexación no acepta rebanar?

pero esta es una pregunta estúpida de mi parte porque olvido que python es dynamic (qué estupidez soy) así que cuando python comstack el código la primera vez que python no sabe si foo es un diccionario o una lista, así que simplemente lee cualquier expresión como esta foo [‘foo’: ‘bar’] como una porción, para saber que puedes hacer:

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

y al usar el módulo dis verá que la expresión 'bar':'foo' se ha convertido automáticamente en una porción:

 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 

en la primera vez que admito que no pensé en esto y fui directamente al código fuente de python tratando de entender por qué, porque el __getitems__ de la lista no es como el __getitem__ de un diccionario, pero ahora entiendo por qué porque si es un slice y slice son unsashable, debería boost el unhashable type , así que aquí está el código del diccionario __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; } .... 

Espero que esto pueda ayudar a algunas personas como yo a comprender la gran respuesta de Ignacio, y disculpe si simplemente duplico la respuesta de Ignacio 🙂