python dictionary

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



dictionary (3)

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.

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


Esta es la ayuda sobre el método fromkeys de dict.

Ayuda sobre la función incorporada de las teclas:

Método fromkeys (iterable, value = None, /) de instancia builtins.type Cree un nuevo diccionario con claves de iterable y valores establecidos en value

Eso dice que fromkeys aceptará un valor, e incluso si es invocable, lo evaluará primero y luego asignará ese valor a todas las claves dict.

Las listas son mutables en Python, por lo que asignará la misma referencia de lista vacía y un cambio los afectará a todos.

Use defaultdict en su lugar como sigue:

>>> from collections import defaultdict >>> one_groups = defaultdict(list) >>> for x in binaries: one_groups[x.count(''1'')] += [x] >>> one_groups = dict(one_groups) # to stop default dict behavior

Esto aceptará asignaciones a claves no existentes y los valores predeterminados serán listas vacías (en este caso).