keys - python dictionary of dictionaries
Dict/Set Parsing Consistencia de la Orden (1)
Contenedores que aceptan objetos hashable (como las claves de dict
o los elementos set
). Como tal, un diccionario solo puede tener una clave con el valor 1
, 1.0
o True
etc. (nota: algo simplificado: se permiten las colisiones de hash, pero estos valores se consideran iguales)
Mi pregunta es: ¿el orden de análisis está bien definido y el objeto resultante es predecible en todas las implementaciones? Por ejemplo, OSX Python 2.7.11 y 3.5.1 interpreta dict
como:
>>> { True: ''a'', 1: ''b'', 1.0: ''c'', (1+0j): ''d'' }
{True: ''d''}
En este caso, parece que la primera clave y el último valor se conservan.
Similar, en el caso del set
:
>>> { True, 1, 1.0, (1+0j) }
set([(1+0j)])
Aquí parece que el último artículo se conserva.
Pero (como se menciona en los comentarios):
>>> set([True, 1, 1.0])
set([True])
Ahora se conserva lo primero en lo iterable.
La documentación señala que el orden de los elementos (por ejemplo, en dict.items
) no está definido, sin embargo, mi pregunta se refiere al resultado de la construcción de dict
o set
objetos.
- El error ahora está arreglado en las versiones recientes de python, como se explica en la respuesta de @jsf
Si se proporciona una secuencia separada por comas de pares clave / referencia, se evalúan de izquierda a derecha para definir las entradas del diccionario: cada objeto clave se utiliza como una clave en el diccionario para almacenar la referencia correspondiente. Esto significa que puede especificar la misma clave varias veces en la lista de claves / datos, y el último valor del diccionario para esa clave será el último.
Una comprensión de dictado, en contraste con la lista y configuración de comprensión, necesita dos expresiones separadas con dos puntos seguidos de las habituales cláusulas "para" y "si". Cuando se ejecuta la comprensión, la clave resultante y los elementos de valor se insertan en el nuevo diccionario en el orden en que se producen.
Una visualización de conjunto produce un nuevo objeto de conjunto mutable, el contenido se especifica mediante una secuencia de expresiones o una comprensión. Cuando se proporciona una lista de expresiones separadas por comas, sus elementos se evalúan de izquierda a derecha y se agregan al objeto establecido. Cuando se proporciona una comprensión, el conjunto se construye a partir de los elementos que resultan de la comprensión.
Hay una diferencia al llamar al constructor del conjunto o al utilizar una comprensión y el literal simple.
def f1():
return {x for x in [True, 1]}
def f2():
return set([True, 1])
def f3():
return {True, 1}
print(f1())
print(f2())
print(f3())
import dis
print("f1")
dis.dis(f1)
print("f2")
dis.dis(f2)
print("f3")
dis.dis(f3)
Salida:
{True}
{True}
{1}
La forma en que se crean influye en el resultado:
605 0 LOAD_CONST 1 (<code object <setcomp> at 0x7fd17dc9a270, file "/home/padraic/Dropbox/python/test.py", line 605>)
3 LOAD_CONST 2 (''f1.<locals>.<setcomp>'')
6 MAKE_FUNCTION 0
9 LOAD_CONST 3 (True)
12 LOAD_CONST 4 (1)
15 BUILD_LIST 2
18 GET_ITER
19 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
22 RETURN_VALUE
f2
608 0 LOAD_GLOBAL 0 (set)
3 LOAD_CONST 1 (True)
6 LOAD_CONST 2 (1)
9 BUILD_LIST 2
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 RETURN_VALUE
f3
611 0 LOAD_CONST 1 (True)
3 LOAD_CONST 2 (1)
6 BUILD_SET 2
9 RETURN_VALUE
Python solo ejecuta el bytecode BUILD_SET
cuando pasas un literal puro separado por comas según:
Cuando se proporciona una lista de expresiones separadas por comas, sus elementos se evalúan de izquierda a derecha y se agregan al objeto establecido.
La línea para la comprensión:
Cuando se proporciona una comprensión, el conjunto se construye a partir de los elementos que resultan de la comprensión.
Entonces, gracias a Hamish que presenta un informe de error , de hecho se reduce al código de operación BUILD_SET
según el comentario de Raymond Hettinger en el enlace.
TARGET(BUILD_SET) {
PyObject *set = PySet_New(NULL);
int err = 0;
if (set == NULL)
goto error;
while (--oparg >= 0) {
PyObject *item = POP();
if (err == 0)
err = PySet_Add(set, item);
Py_DECREF(item);
}
if (err != 0) {
Py_DECREF(set);
goto error;
}
PUSH(set);
DISPATCH();
}