¿Cómo devolver claves de diccionario como una lista en Python?

1021

En Python 2.7 , podría obtener claves de diccionario , valores o elementos como una lista:

>>> newdict = {1:0, 2:0, 3:0}
>>> newdict.keys()
[1, 2, 3]

Ahora, en Python> = 3.3 , obtengo algo como esto:

>>> newdict.keys()
dict_keys([1, 2, 3])

Entonces, tengo que hacer esto para obtener una lista:

newlist = list()
for i in newdict.keys():
    newlist.append(i)

Me pregunto, ¿hay una mejor manera de devolver una lista en Python 3 ?

2
  • Un problema de seguridad de subprocesos interesante con respecto a este tema está aquí: blog.labix.org/2008/06/27/…Paul 10 de mayo de 2016 a las 18:00
  • 9
    Soy nuevo en Python, y me parece que esta proliferación de nuevos tipos de datos inútiles es uno de los peores aspectos de Python. ¿De qué sirve este tipo de datos dict_keys? ¿Por qué no una lista? Phil Goetz 9 abr.20 a las 20:22
1294

Prueba list(newdict.keys()).

Esto convertirá el dict_keysobjeto en una lista.

Por otro lado, debes preguntarte si importa o no. La forma Pythonic de codificar es asumir que se escribe pato ( si parece un pato y grazna como un pato, es un pato ). El dict_keysobjeto actuará como una lista para la mayoría de los propósitos. Por ejemplo:

for key in newdict.keys():
  print(key)

Obviamente, los operadores de inserción pueden no funcionar, pero eso no tiene mucho sentido para una lista de claves de diccionario de todos modos.

10
  • 76
    newdict.keys () no admite la indexacióngypaetus 10 de septiembre de 2014 a las 17:54
  • 80
    list(newdict)también funciona (al menos en Python 3.4). ¿Hay alguna razón para utilizar el .keys()método? naught101 31/03/15 a las 11:58
  • 55
    Nota: en el depurador pdb> list(newdict.keys()) falla porque choca con el comando pdb del mismo nombre. Úselo pdb> !list(newdict.keys())para escapar de los comandos pdb. Riaz Rizvi 24/12/2016 a las 20:37
  • 31
    @ naught101 Sí, .keys()es mucho más claro lo que sucede. Felix D. 27 de mayo de 2018 a las 21:43
  • 3
    Tenga en cuenta que si usa list (newdict.keys ()), las claves no están en el orden en que las colocó debido al orden hash. Nate M 30 de enero de 2019 a las 3:28
388

Python> = 3.5 alternativa: descomprimir en una lista literal [*newdict]

Se introdujeron nuevas generalizaciones de descompresión (PEP 448) con Python 3.5, lo que le permite hacer ahora fácilmente:

>>> newdict = {1:0, 2:0, 3:0}
>>> [*newdict]
[1, 2, 3]

Desempaquetar con *funciona con cualquier objeto que sea iterable y, dado que los diccionarios devuelven sus claves cuando se repiten, puede crear fácilmente una lista usándola dentro de un literal de lista.

Agregar .keys()ie [*newdict.keys()]podría ayudar a hacer su intención un poco más explícita, aunque le costará una búsqueda e invocación de la función. (lo cual, con toda honestidad, no es algo de lo que debas preocuparte).

La *iterablesintaxis es similar a la de hacer list(iterable)y su comportamiento se documentó inicialmente en la sección Llamadas del manual de referencia de Python. Con PEP 448 *iterablese aflojó la restricción sobre dónde podía aparecer, lo que permite que también se coloque en literales de lista, conjunto y tupla, el manual de referencia sobre listas de expresiones también se actualizó para indicar esto.


Aunque es equivalente a list(newdict)con la diferencia de que es más rápido (al menos para diccionarios pequeños) porque en realidad no se realiza ninguna llamada de función:

%timeit [*newdict]
1000000 loops, best of 3: 249 ns per loop

%timeit list(newdict)
1000000 loops, best of 3: 508 ns per loop

%timeit [k for k in newdict]
1000000 loops, best of 3: 574 ns per loop

con diccionarios más grandes, la velocidad es prácticamente la misma (la sobrecarga de iterar a través de una colección grande supera el pequeño costo de una llamada de función).


De manera similar, puede crear tuplas y conjuntos de claves de diccionario:

>>> *newdict,
(1, 2, 3)
>>> {*newdict}
{1, 2, 3}

¡cuidado con la coma final en el caso de la tupla!

5
  • gran explicación, pero por favor, puede consultar cualquier enlace que describa este tipo de sintaxis "* newdict", me refiero a cómo y por qué esto devuelve las claves del diccionario solo para su comprensiónMuhammad Younus 7 de abril de 2018 a las 2:56
  • 2
    @MYounas Esa sintaxis ha estado disponible durante bastante tiempo, incluso en Python 2. En las llamadas a funciones, puede hacerlo def foo(*args): print(args)seguido de foo(*{1:0, 2:0})la (1, 2)impresión del resultado . Este comportamiento se especifica en la sección Llamadas del manual de referencia. Python 3.5 con PEP 448 acaba de aflojar las restricciones sobre dónde pueden aparecer, lo [*{1:0, 2:0}]que permite su uso ahora. De cualquier manera, editaré mi respuesta e incluiré estos. Dimitris Fasarakis Hilliard 7 de abril de 2018 a las 10:56
  • 3
    *newdict- esta es definitivamente la respuesta para los golfistas de código; P. Además: lo cual, con toda honestidad, no es algo de lo que debas preocuparte , y si es así, no uses Python . Artemis 5 abr 19 a las 14:26
  • 1
    Hoy aprendí dos cosas: 1. Puedo acortar list(some_dict.keys())a [*some_dict], 2. La expresión "golfista codificado" (y 2a. El significado de "golfista codificado", después de buscar en Google)kasimir 8 de julio de 2020 a las 12:16
  • Gracias, esta respuesta es realmente útil. Kris Stern 12 nov.20 a las 11:04
57

list(newdict)funciona tanto en Python 2 como en Python 3, proporcionando una lista simple de las claves en newdict. keys()no es necesario. (:

0
29

Un poco fuera de la definición de "escritura de pato": dict.keys()devuelve un objeto iterable, no un objeto similar a una lista. Funcionará en cualquier lugar donde funcione un iterable, no en cualquier lugar en el que funcione una lista. una lista también es iterable, pero una iterable NO es una lista (o secuencia ...)

En casos de uso reales, lo más común que se puede hacer con las claves en un dictado es recorrerlas en iteración, por lo que esto tiene sentido. Y si los necesita como una lista, puede llamar list().

De manera muy similar zip(), en la gran mayoría de los casos, se repite, ¿por qué crear una lista completamente nueva de tuplas solo para iterar y luego desecharla nuevamente?

Esto es parte de una gran tendencia en Python de usar más iteradores (y generadores), en lugar de copias de listas por todas partes.

dict.keys() Sin embargo, debería funcionar con comprensiones, verifique cuidadosamente si hay errores tipográficos o algo ... funciona bien para mí:

>>> d = dict(zip(['Sounder V Depth, F', 'Vessel Latitude, Degrees-Minutes'], [None, None]))
>>> [key.split(", ") for key in d.keys()]
[['Sounder V Depth', 'F'], ['Vessel Latitude', 'Degrees-Minutes']]
1
  • 3
    Ni siquiera necesitas usar .keys(); el objeto de diccionario es en sí iterable y produce teclas cuando se repiten a lo largo: [key.split(", ") for key in d]. Martijn Pieters 27/09/19 a las 12:16
29

También puede utilizar una lista de comprensión :

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

O, más corto,

>>> [k  for  k in  newdict]
[1, 2, 3]

Nota: el pedido no está garantizado en versiones inferiores a 3.7 (el pedido sigue siendo solo un detalle de implementación con CPython 3.6).

1
  • 12
    Solo usa list(newdict). No es necesario comprender una lista aquí. Martijn Pieters 27/09/19 a las 12:15
13

Si necesita almacenar las claves por separado, aquí hay una solución que requiere menos escritura que cualquier otra solución presentada hasta ahora, utilizando el Desempaquetado Iterable Extendido (python3.x +).

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
            │ k = list(d)   │   9 characters (excluding whitespace)   │
            ├───────────────┼─────────────────────────────────────────┤
            │ k = [*d]      │   6 characters                          │
            ├───────────────┼─────────────────────────────────────────┤
            │ *k, = d       │   5 characters                          │
            ╘═══════════════╧═════════════════════════════════════════╛
4
  • 1
    La única advertencia menor que señalaría es que ksiempre hay una lista aquí. Si un usuario quiere una tupla o un conjunto de claves, deberá recurrir a las otras opciones. Dimitris Fasarakis Hilliard 5 abr 19 a las 17:45
  • 1
    Una nota más notable es el hecho de que, como declaración, *k, = dtiene limitaciones sobre dónde puede aparecer (pero vea, y tal vez actualice esta respuesta para, PEP 572 : el desempaquetado extendido no es compatible con las expresiones de asignación atm, ¡ pero podría serlo algún día! )Dimitris Fasarakis Hilliard 5 abr 19 a las 17:55
  • ¿Qué pasa si desea tanto las claves como los valores en las listas? endolith 26/08/19 a las 23:26
  • 2
    @endolith quizás keys, vals = zip(*d.items())(aunque eso da dos tuplas, lo suficientemente cerca). No conozco una expresión más corta que esta. cs95 26/08/19 a las 23:45
12

Convertir a una lista sin usar el keysmétodo lo hace más legible:

list(newdict)

y, al recorrer los diccionarios, no es necesario keys():

for key in newdict:
    print key

a menos que lo esté modificando dentro del bucle, lo que requeriría una lista de claves creadas de antemano:

for key in list(newdict):
    del newdict[key]

En Python 2 hay una ganancia de rendimiento marginal al usarkeys() .

3

Puedo pensar en 2 formas en las que podemos extraer las claves del diccionario.

Método 1: - Para obtener las claves usando el método .keys () y luego convertirlas en una lista.

some_dict = {1: 'one', 2: 'two', 3: 'three'}
list_of_keys = list(some_dict.keys())
print(list_of_keys)
-->[1,2,3]

Método 2: - Para crear una lista vacía y luego agregar claves a la lista a través de un bucle. También puede obtener los valores con este ciclo (use .keys () solo para claves y .items () para extracción de claves y valores)

list_of_keys = []
list_of_values = []
for key,val in some_dict.items():
    list_of_keys.append(key)
    list_of_values.append(val)

print(list_of_keys)
-->[1,2,3]

print(list_of_values)
-->['one','two','three']
1

Sé que esta es una respuesta muy antigua, pero más allá de la forma clásica (y probablemente más correcta) de hacer esto ( some_dict.keys()) también hay una forma más "genial" y seguramente más interesante de hacer esto:

some_dict = { "foo": "bar", "cool": "python!" }
print( [*some_dict] == ["foo", "cool"] )         # True  

Nota: esta solución no debe utilizarse en un entorno de desarrollo; Lo mostré aquí solo porque pensé que era bastante interesante desde el *punto de vista del operador sobre el diccionario.

-1

Esta es la mejor manera de obtener la lista de claves en una línea de código

dict_variable = {1:"a",2:"b",3:"c"}  
[key_val for key_val in dict_variable.keys()]
1
  • Creo que quería decir[key_val for key_val in dict_variable.keys()]Aashutosh Rathi 26 de junio a las 8:12