python - ¿Por qué funcionó dict.get(key) pero no dict[key]?




dictionary (2)

Estoy tratando de agrupar las cadenas binarias de ciertos números en función de cuántos 1 hay en la cadena.

Esto no funciona

s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]

one_groups = dict.fromkeys(range(5), [])
for x in binaries:
    one_groups[x.count('1')] += [x]

El diccionario esperado one_groups debe ser

{0: ['0000'], 
 1: ['0001', '1000'], 
 2: ['0011', '1001'], 
 3: ['0111', '1011'], 
 4: ['1111']}

Pero consigo

{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'], 
 4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}

Hasta ahora, lo único que ha funcionado es si uso one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x] lugar de one_groups[x.count('1')] += [x]

¿Pero por qué es así? Si recuerdo correctamente, ¿no se supone que dict[key] devuelve el valor de ese diccionario, de forma similar a cómo funciona dict.get(key) ? He visto este hilo ¿Por qué dict.get (key) en lugar de dict [key]? pero no respondió mi pregunta para este caso en particular, ya que sé con certeza que el programa no está destinado a obtener KeyError

También probé one_groups[x.count('1')].append(x) pero esto tampoco funciona.


El problema es la mutabilidad:

one_groups = dict.fromkeys(range(5), []) : esto pasa la misma lista como valor a todas las claves . Entonces, si cambia un valor, los cambia a todos.

Es básicamente lo mismo que decir:

tmp = []
one_groups = dict.fromkeys(range(5), tmp)
del tmp

Si desea utilizar una nueva lista, debe hacerlo en un bucle, ya sea explícito for bucle o en una comprensión dict:

one_groups = {key: [] for key in range(5)}

Esta cosa "ejecutará" [] (que equivale a list() ) para cada clave, haciendo así los valores con diferentes listas.

¿Por qué get trabajo? Porque tomas explícitamente la lista actual, pero + crea una nueva lista de resultados. Y no importa si es one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x] o one_groups[x.count('1')] = one_groups[x.count('1')] + [x] - lo que importa es que hay + .

Sé cómo todos dicen que a+=b es solo a=a+b , pero la implementación puede ser diferente para la optimización: en el caso de las listas, += es solo .extend porque sabemos que queremos nuestro resultado en la variable actual, por lo que crear nueva lista sería una pérdida de memoria.


El problema es usar one_groups = dict.fromkeys(range(5), [])

(Esto pasa la misma lista como valor a todas las claves. Entonces, si cambia un valor, los cambia a todos)

En su lugar, puede usar esto: one_groups = {i:[] for i in range(5)}

(Esta cosa "ejecutará" [] (lo que equivale a list ()) para cada clave, haciendo así los valores con diferentes listas).





dictionary