Solo quiero agregar algunos detalles al Ignacio answer (lo cual es genial) y eso me lleva algo de tiempo entender y para gente como yo que no lo entendió (puede que yo sea el único que no lo entendió) porque no vi a nadie preguntando no entendí, pero ¿cómo sabe :)):
la primera vez que me pregunto qué rebanada? indexación del diccionario no acepta rebanar?
pero esto es una pregunta estúpida de mi parte porque me olvido de que Python es dinámico (lo estúpida que soy) por lo que cuando pitón compilar el código de la pitón tiempo del puño no sé si foo
es un diccionario o una lista por lo que acaba de leer cualquier expresión como esta foo [ 'foo': 'bar'] como una rebanada, para saber que sólo se puede hacer:
def f():
foo = {}
foo['bar':'foo']
y mediante el uso dis módulo se verá que la expresión 'bar':'foo'
tiene se ha convertido automáticamente a 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 admito que no pensé en esto y fui directamente al código fuente de python tratando de entender por qué, porque __getitems__
de la lista no es como __getitem__
de un diccionario pero ahora entiendo por qué porque si que una rebanada y rebanada son unhashable no debe plantear unhashable type
, así que aquí está el código de 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;
}
....
la esperanza que esto puede ayudar a algunas personas como yo entiendo la gran respuesta de Ignacio, y lo siento si acabo de duplico la respuesta de Ignacio :)
Tengo que admitir que no se me ocurrió. +1 – delnan