Wie gebe ich Wörterbuchschlüssel als Liste in Python zurück?

781

In Python 2.7 , konnte ich Wörterbuch erhalten Schlüssel , Werte oder Elemente als Liste:

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

In Python> = 3.3 erhalte ich ungefähr Folgendes:

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

Also muss ich das tun, um eine Liste zu bekommen:

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

Ich frage mich, gibt es eine bessere Möglichkeit, eine Liste in Python 3 zurückzugeben ?

Dimitris Fasarakis Hilliard
quelle
Interessante Thread-Sicherheitsprobleme zu diesem Thema finden Sie hier: blog.labix.org/2008/06/27/…
Paul
2
Ich bin neu in Python und für mich scheint diese Verbreitung nutzloser neuer Datentypen einer der schlimmsten Aspekte von Python zu sein. Was nützt dieser Datentyp dict_keys? Warum nicht eine Liste?
Phil Goetz

Antworten:

977

Versuchen Sie es list(newdict.keys()).

Dadurch wird das dict_keysObjekt in eine Liste konvertiert .

Auf der anderen Seite sollten Sie sich fragen, ob es wichtig ist oder nicht. Die pythonische Art zu codieren besteht darin, die Ententypisierung anzunehmen ( wenn es wie eine Ente aussieht und wie eine Ente quakt, ist es eine Ente ). Das dict_keysObjekt verhält sich für die meisten Zwecke wie eine Liste. Zum Beispiel:

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

Einfügeoperatoren funktionieren natürlich möglicherweise nicht, aber das macht für eine Liste von Wörterbuchschlüsseln sowieso nicht viel Sinn.

Chris
quelle
49
newdict.keys () unterstützt keine Indizierung
Gypaetus
57
list(newdict)funktioniert auch (zumindest in Python 3.4). Gibt es einen Grund, die .keys()Methode anzuwenden ?
naught101
46
Hinweis: Der Debugger pdb> list(newdict.keys()) schlägt fehl, da er mit dem gleichnamigen Befehl von pdb kollidiert. Verwenden Sie pdb> !list(newdict.keys())diese Option, um pdb-Befehlen zu entkommen.
Riaz Rizvi
24
@ naught101 Ja, .keys()ist viel klarer, was los ist.
Felix D.
2
Beachten Sie, dass bei Verwendung von list (newdict.keys ()) die Schlüssel aufgrund der Hashing-Reihenfolge nicht in der Reihenfolge sind, in der Sie sie platziert haben!
Nate M
277

Python> = 3.5 Alternative: In ein Listenliteral entpacken [*newdict]

Mit Python 3.5 wurden neue Verpackungsverallgemeinerungen (PEP 448) eingeführt, mit denen Sie jetzt ganz einfach Folgendes tun können:

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

Das Entpacken mit *funktioniert mit jedem iterierbaren Objekt. Da Wörterbücher ihre Schlüssel beim Durchlaufen zurückgeben, können Sie eine Liste einfach erstellen, indem Sie sie in einem Listenliteral verwenden.

Das Hinzufügen von .keys()dh kann [*newdict.keys()]dazu beitragen, Ihre Absicht ein wenig deutlicher zu machen, obwohl es Sie eine Funktionssuche und einen Aufruf kostet. (worüber Sie sich ehrlich gesagt keine Sorgen machen sollten).

Die *iterableSyntax ähnelt der von Doing list(iterable)und ihr Verhalten wurde ursprünglich in der Dokumentation dokumentiert Abschnitt Aufrufe des Python-Referenzhandbuchs dokumentiert. Mit PEP 448 wurde die Beschränkung, wo *iterableangezeigt werden kann, gelockert, sodass es auch in Listen-, Set- und Tupelliterale eingefügt werden kann. Das Referenzhandbuch zu Ausdruckslisten wurde ebenfalls aktualisiert, um dies anzugeben.


Obwohl gleichbedeutend list(newdict)mit dem Unterschied, dass es schneller ist (zumindest für kleine Wörterbücher), weil tatsächlich kein Funktionsaufruf ausgeführt wird:

%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

Bei größeren Wörterbüchern ist die Geschwindigkeit nahezu gleich (der Aufwand für das Durchlaufen einer großen Sammlung übertrifft die geringen Kosten eines Funktionsaufrufs).


Auf ähnliche Weise können Sie Tupel und Sätze von Wörterbuchschlüsseln erstellen:

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

Achten Sie auf das nachfolgende Komma im Tupelgehäuse!

Dimitris Fasarakis Hilliard
quelle
Gute Erklärung, aber bitte können Sie auf einen beliebigen Link verweisen, der diese "* newdict" -Syntax beschreibt. Ich meine, wie und warum dies die Schlüssel aus dem Wörterbuch nur zum Verständnis zurückgibt. Danke
Muhammad Younus
1
@MYounas Das Syntax hat seit geraumer Zeit auch in Python 2. In Funktion zur Verfügung ruft Sie kann def foo(*args): print(args)durch gefolgt foo(*{1:0, 2:0})mit dem Ergebnis (1, 2)gedruckt wird. Dieses Verhalten wird im Abschnitt Anrufe des Referenzhandbuchs angegeben. Python 3.5 mit PEP 448 hat gerade die Einschränkungen gelockert, wo diese angezeigt werden können, sodass [*{1:0, 2:0}]sie jetzt verwendet werden können. In jedem Fall werde ich meine Antwort bearbeiten und diese einschließen.
Dimitris Fasarakis Hilliard
1
*newdict- Dies ist definitiv die Antwort für Code-Golfer; P. Außerdem: Worüber Sie sich ehrlich gesagt keine Sorgen machen sollten - und wenn ja , verwenden Sie kein Python .
Artemis vertraut SE am
46

list(newdict)funktioniert sowohl in Python 2 als auch in Python 3 und bietet eine einfache Liste der Schlüssel in newdict. keys()ist nicht notwendig. (:

Seb
quelle
26

Ein bisschen abweichend von der Definition der "Ententypisierung" - dict.keys() gibt ein iterierbares Objekt zurück, kein listenähnliches Objekt. Es wird überall dort funktionieren, wo eine Iterable funktioniert - nicht an jedem Ort, an dem eine Liste funktioniert. Eine Liste ist auch eine Iterable, aber eine Iterable ist KEINE Liste (oder Sequenz ...)

In realen Anwendungsfällen ist es am häufigsten, die Schlüssel in einem Diktat zu durchlaufen, um sie zu durchlaufen. Dies ist also sinnvoll. Und wenn Sie sie als Liste benötigen, können Sie anrufen list().

Ganz ähnlich, denn zip()- in den allermeisten Fällen wird es durchlaufen - warum sollte eine ganz neue Liste von Tupeln erstellt werden, um sie zu durchlaufen und dann wieder wegzuwerfen?

Dies ist Teil eines großen Trends in Python, mehr Iteratoren (und Generatoren) anstelle von Kopien von Listen überall zu verwenden.

dict.keys() sollte aber mit Verständnis funktionieren - sorgfältig auf Tippfehler oder ähnliches prüfen ... es funktioniert gut für mich:

>>> 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']]
Chris Barker
quelle
2
Sie müssen nicht einmal verwenden .keys(); Das Wörterbuchobjekt ist selbst iterierbar und erzeugt Schlüssel, wenn es wiederholt wird : [key.split(", ") for key in d].
Martijn Pieters
25

Sie können auch ein Listenverständnis verwenden :

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

Oder kürzer,

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

Hinweis: Die Reihenfolge ist bei Versionen unter 3.7 nicht garantiert (die Bestellung ist bei CPython 3.6 immer noch nur ein Implementierungsdetail).

未来 陆家嘴 顶尖 的 投资 投资
quelle
6
Einfach benutzen list(newdict). Hier ist kein Listenverständnis erforderlich.
Martijn Pieters
8

Das Konvertieren in eine Liste ohne Verwendung der keysMethode macht sie besser lesbar:

list(newdict)

und beim Durchlaufen von Wörterbüchern ist Folgendes nicht erforderlich keys():

for key in newdict:
    print key

es sei denn, Sie ändern es innerhalb der Schleife, für die eine Liste der zuvor erstellten Schlüssel erforderlich wäre:

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

Unter Python 2 gibt es einen geringfügigen Leistungsgewinn bei Verwendung vonkeys() .

Cas
quelle
8

Wenn Sie die Schlüssel separat speichern müssen, finden Sie hier eine Lösung, die weniger Eingabe erfordert als jede andere bisher vorgestellte Lösung, die Extended Iterable Unpacking (python3.x +) verwendet.

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                          
            ╘═══════════════╧═════════════════════════════════════════╛
cs95
quelle
1
Die einzige kleine Einschränkung, auf die ich hinweisen möchte, ist, dass kes hier immer eine Liste gibt. Wenn ein Benutzer ein Tupel oder eine Einstellung über die Tasten wünscht, muss er auf die anderen Optionen zurückgreifen.
Dimitris Fasarakis Hilliard
1
Ein bemerkenswerterer Hinweis ist die Tatsache, dass die Aussage als Aussage *k, = dEinschränkungen aufweist, wo sie angezeigt werden kann (siehe jedoch und aktualisieren Sie möglicherweise diese Antwort für PEP 572 - erweitertes Entpacken wird für Zuweisungsausdrücke atm nicht unterstützt , könnte aber eines Tages sein! )
Dimitris Fasarakis Hilliard
Was ist, wenn Sie möchten, dass sowohl die Schlüssel als auch die Werte aufgelistet werden?
Endolith
1
@endolith vielleicht keys, vals = zip(*d.items())(obwohl das zwei Tupel gibt, nah genug). Ich kenne keinen kürzeren Ausdruck als diesen.
CS95
1

Ich kann mir zwei Möglichkeiten vorstellen, wie wir die Schlüssel aus dem Wörterbuch extrahieren können.

Methode 1: - Um die Schlüssel mit der .keys () -Methode abzurufen und dann in eine Liste zu konvertieren.

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

Methode 2: - Erstellen einer leeren Liste und Anhängen von Schlüsseln an die Liste über eine Schleife. Sie können die Werte auch mit dieser Schleife abrufen (verwenden Sie .keys () nur für Schlüssel und .items () für die Schlüssel- und Wertextraktion).

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']
Rahul
quelle