Jak zwrócić klucze słownika jako listę w Pythonie?

778

W Pythonie 2.7 mogłem uzyskać klucze , wartości lub elementy słownika jako listę:

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

Teraz w Pythonie> = 3.3 otrzymuję coś takiego:

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

Więc muszę to zrobić, aby uzyskać listę:

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

Zastanawiam się, czy jest lepszy sposób na zwrócenie listy w Pythonie 3 ?

Dimitris Fasarakis Hilliard
źródło
Ciekawe zagadnienie bezpieczeństwa wątków dotyczące tego tematu znajduje się tutaj: blog.labix.org/2008/06/27/...
Paul
2
Jestem nowy w Pythonie i wydaje mi się, że mnożenie bezużytecznych nowych typów danych jest jednym z najgorszych aspektów Pythona. Jaki jest pożytek z tego typu danych dict_keys? Dlaczego nie lista?
Phil Goetz

Odpowiedzi:

975

Spróbować list(newdict.keys()).

Spowoduje to konwersję dict_keysobiektu do listy.

Z drugiej strony powinieneś zadać sobie pytanie, czy to ma znaczenie, czy nie. Pythoński sposób kodowania polega na zakładaniu pisania kaczki ( jeśli wygląda jak kaczka i kwacze jak kaczka, to jest kaczka ). W dict_keyswiększości przypadków obiekt będzie działał jak lista. Na przykład:

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

Oczywiście operatory wstawiania mogą nie działać, ale i tak nie ma to większego sensu dla listy kluczy słowników.

Chris
źródło
49
newdict.keys () nie obsługuje indeksowania
gypaetus,
57
list(newdict)działa również (przynajmniej w Pythonie 3.4). Czy jest jakiś powód, aby użyć tej .keys()metody?
naught101
46
Uwaga: debugger pdb> list(newdict.keys()) nie działa, ponieważ koliduje z poleceniem pdb o tej samej nazwie. Służy pdb> !list(newdict.keys())do zmiany komend pdb.
Riaz Rizvi
23
@ naught101 Tak, .keys()jest bardziej jasne, co się dzieje.
Felix D.
2
Zauważ, że jeśli użyjesz list (newdict.keys ()), że klucze nie są w kolejności, w której je umieściłeś z powodu kolejności mieszania!
Nate M
276

Python> = 3.5 alternatywa: rozpakuj do literału listy [*newdict]

Nowe uogólnienia dotyczące rozpakowywania (PEP 448) zostały wprowadzone w Pythonie 3.5, umożliwiając łatwe wykonywanie:

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

Rozpakowywanie za pomocą *działa z każdym obiektem, który można iterować, a ponieważ słowniki zwracają klucze podczas iteracji, możesz łatwo utworzyć listę, używając jej w literale listy.

Dodanie .keys()np. [*newdict.keys()]Może pomóc w uczynieniu twojej intencji nieco bardziej wyraźną, chociaż będzie to kosztowało wyszukiwanie funkcji i wywoływanie. (co, szczerze mówiąc , nie powinieneś się tym martwić).

*iterableSkładnia jest podobna do robienia list(iterable), a jego zachowanie było początkowo udokumentowane w sekcji Połączenia podręcznika Python Reference. W przypadku PEP 448 zlikwidowano ograniczenie dotyczące miejsca, w którym *iterablemoże się pojawić, pozwalając na umieszczenie go również w literałach list, set i krotkach, zaktualizowano również podręcznik referencyjny list wyrażeń .


Jest to równoważne list(newdict)z tą różnicą, że jest szybsze (przynajmniej w przypadku małych słowników), ponieważ w rzeczywistości nie jest wykonywane żadne wywołanie funkcji:

%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

w przypadku większych słowników prędkość jest prawie taka sama (narzut związany z iteracją przez dużą kolekcję przewyższa niewielki koszt wywołania funkcji).


W podobny sposób możesz tworzyć krotki i zestawy kluczy słownika:

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

uważaj na końcowy przecinek w krotce!

Dimitris Fasarakis Hilliard
źródło
świetne wyjaśnienie, ale czy możesz odnieść się do dowolnego linku opisującego tę składnię typu „* newdict”, mam na myśli, jak i dlaczego zwraca klucze ze słownika tylko dla zrozumienia.
Tanx
1
@MYounas Ta składnia jest dostępna już od dłuższego czasu, nawet w Pythonie 2. W wywołaniach funkcji można wykonać, def foo(*args): print(args)a następnie wydrukować foo(*{1:0, 2:0})wynik (1, 2). To zachowanie jest określone w sekcji Połączenia podręcznika referencyjnego. Python 3.5 z PEP 448 właśnie poluzował ograniczenia dotyczące tego, gdzie mogą się pojawiać, umożliwiając [*{1:0, 2:0}]teraz ich użycie. Tak czy inaczej, zmienię odpowiedź i dołączę je.
Dimitris Fasarakis Hilliard
1
*newdict- to zdecydowanie odpowiedź dla golfistów kodowych; P. Ponadto: co, szczerze mówiąc, nie jest czymś, o co powinieneś się martwić - a jeśli tak, nie używaj Pythona .
Artemis nadal nie ufa SE
46

list(newdict)działa zarówno w Python 2, jak i Python 3, zapewniając prostą listę kluczy w newdict. keys()nie jest konieczne. (:

Seb
źródło
26

Nieco w definicji „typowania kaczki” - dict.keys()zwraca obiekt powtarzalny, a nie obiekt podobny do listy. Będzie działać wszędzie, gdzie będzie działał iterowalny - nie w żadnym miejscu listy. lista jest także iterowalna, ale iterowalna NIE jest listą (lub sekwencją ...)

W rzeczywistych przypadkach użycia, najczęstszą rzeczą związaną z kluczami w nagraniu jest iteracja przez nie, więc ma to sens. A jeśli potrzebujesz ich jako listy, możesz zadzwonić list().

Bardzo podobnie, ponieważ zip()- w zdecydowanej większości przypadków jest iterowana - po co tworzyć nową listę krotek, aby ją powtarzać, a następnie wyrzucić?

Jest to część dużego trendu w Pythonie, aby używać większej liczby iteratorów (i generatorów), a nie kopii list w całym miejscu.

dict.keys() powinien jednak działać ze zrozumieniem - dokładnie sprawdź literówki lub coś ... działa dla mnie dobrze:

>>> 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
źródło
2
Nie musisz nawet używać .keys(); słownik obiekt jest sama iterable i produkuje klucze kiedy powtórzyć nad: [key.split(", ") for key in d].
Martijn Pieters
25

Możesz także skorzystać ze zrozumienia listy :

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

Lub krócej

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

Uwaga: Zamówienie nie jest gwarantowane w wersjach poniżej 3.7 (zamawianie to nadal tylko szczegół implementacji w CPython 3.6).

未来 陆家嘴 顶尖 的 投资 人
źródło
6
Po prostu użyj list(newdict). Nie ma tu potrzeby rozumienia listy.
Martijn Pieters
8

Konwersja na listę bez korzystania z keysmetody czyni ją bardziej czytelną:

list(newdict)

a podczas przeglądania pętli słowników nie ma potrzeby keys():

for key in newdict:
    print key

chyba że modyfikujesz go w pętli, co wymagałoby wcześniej utworzonej listy kluczy:

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

W Pythonie 2 użycie marginalnego przyrostu wydajności jest niewielkiekeys() .

Cas
źródło
8

Jeśli potrzebujesz przechowywać klucze osobno, oto rozwiązanie, które wymaga mniej pisania niż każde inne przedstawione do tej pory rozwiązanie, używając Extended Iterable Unpacking (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                          
            ╘═══════════════╧═════════════════════════════════════════╛
cs95
źródło
1
Jedynym drobnym zastrzeżeniem, na które zwracam uwagę, jest to, że kzawsze jest tutaj lista. Jeśli użytkownik chce krotkę lub zestaw z kluczy, musi wrócić do innych opcji.
Dimitris Fasarakis Hilliard,
1
Bardziej godnym uwagi jest fakt, że jako stwierdzenie *k, = dma ograniczenia dotyczące miejsca, w którym może się pojawić (ale zobacz, a może zaktualizuj tę odpowiedź, PEP 572 - rozszerzone rozpakowywanie nie jest obsługiwane dla wyrażeń przypisania atm, ale może być kiedyś! )
Dimitris Fasarakis Hilliard,
co jeśli chcesz, aby klucze i wartości były wyświetlane na listach?
endolith
1
@endolith może keys, vals = zip(*d.items())(chociaż daje to dwie krotki, wystarczająco blisko). Nie znam krótszego wyrazu niż ten.
cs95,
1

Mogę wymyślić 2 sposoby wydobywania kluczy ze słownika.

Metoda 1: - Aby uzyskać klucze za pomocą metody .keys (), a następnie przekonwertować na listę.

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

Metoda 2: - Aby utworzyć pustą listę, a następnie dołączyć do niej klucze za pomocą pętli. Możesz również uzyskać wartości za pomocą tej pętli (użyj .keys () tylko dla kluczy i .items () zarówno dla wydobycia kluczy, jak i wartości)

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
źródło