2013-07-13 11 views
17

Niedawno napisałem jakiś kod, który wyglądał mniej więcej tak:Dlaczego warto korzystać z dict.keys?

# dct is a dictionary 
if "key" in dct.keys(): 

Jednak później okazało, że mogę osiągnąć te same wyniki z:

if "key" in dct: 

Odkrycie to dało mi do myślenia i zacząłem uruchom niektóre testy, aby sprawdzić, czy może istnieć scenariusz, gdy I musi użyć metody ze słownika w postaci keys. Mój wniosek brzmi jednak nie, nie ma.

Jeśli chcę klucze w wykazie, co mogę zrobić:

keys_list = list(dct) 

Jeśli chcę iteracyjne nad klucze, mogę zrobić:

for key in dct: 
    ... 

Wreszcie, jeśli chcę sprawdzić, czy klucz jest w dct, mogę użyć in, tak jak powyżej.

Podsumowując, moje pytanie brzmi: czy czegoś brakuje? Czy kiedykolwiek byłby scenariusz, w którym I musi użyć metody keys? ... lub jest to po prostu metoda resztkowa z wcześniejszej instalacji Pythona, która powinna być zignorowana?

+0

Jeśli funkcja 'dct.keys()' jest bardziej wydajna, podczas pobierania kluczy jako listy _wartość_. Teraz 'jeśli klucz w dct' działa, jednak za każdym razem wyszukiwanie wymagałoby dodatkowego przetwarzania. To jest optymalizacja. – karthikr

+3

Jawny jest lepszy niż niejawny. –

+1

@karthikr: w obu przypadkach 'for' tworzy obiekt iteratora (wartość zwracaną przez funkcję' iter() ', która daje wartości w sekwencji Oba przypadki zwracają klucze słownika, z tą różnicą, że używając' dict.keys() 'wymaga wyszukiwania atrybutu i wywołania funkcji * first *. W ten sposób jest mniej efektywny –

Odpowiedz

20

W Pythonie 3, użyj dct.keys() dostać dictionary view object, który pozwala zrobić tylko zestaw operacji na klawiszach:

>>> for sharedkey in dct1.keys() & dct2.keys(): # intersection of two dictionaries 
...  print(dct1[sharedkey], dct2[sharedkey]) 

W Pythonie 2, można użyć dct.viewkeys() do tego.

W języku Python 2, dct.keys() zwraca listę, kopię kluczy w słowniku. Można to przekazać wokół osobnego obiektu, który można samodzielnie zmanipulować, włączając usuwanie elementów bez wpływu na sam słownik; można jednak utworzyć tę samą listę z list(dct), która działa zarówno w języku Python 2, jak i 3.

Naprawdę nie chcesz żadnych z nich do testowania iteracji lub członkostwa; zawsze używaj odpowiednio for key in dct i key in dct.

2

Zakładając, że nie używasz Pythona 3, list(dct) jest równoważne dct.keys(). To, którego używasz, jest kwestią osobistych preferencji. Osobiście uważam, że dct.keys() jest nieco jaśniejszy, ale do każdego z nich.

W żadnym przypadku nie ma scenariusza, w którym "trzeba" użyć, aby używać dct.keys() per se.

W Pythonie 3 dct.keys() zwraca „Dictionary obiektu widoku”, więc jeśli chcesz uzyskać luku unmaterialized celu klawiszy (który może być przydatny dla wielkich słowników) poza kontekst for pętli, ty” musisz użyć dct.keys().

+1

Zgadzam się z tom. dct.keys() jest bardziej tradycyjny i idiomatyczny python (np. 'pythonic'). Podstępne sztuczki składniowe, takie jak' list (dct) 'są bardziej chwytliwe niż idiomatyczne użycie - wiele timów es a noob python użytkownik musiałby wykopać trochę głębiej, aby określić, czy 'list (dct)' zwraca listę kluczy lub listę elementów. dct.keys() jest jednoznaczny i czytelny na początku inspekcji dla każdego, kto czyta twój kod, nawet do pytona nooba. 'dla klucza w dct' jest w porządku, ponieważ jest to idiomatyczne użycie pythona. – linguanerd

+0

Technicznie "dct.keys()" jest "obiektem widoku słownikowego" w Pythonie 3, a nie iteratorem: 'type (dct.keys())' jest '' while 'type (iter (dct))) 'jest' '. (Zobacz odpowiedzi Martijna i user2357112.) Stąd 'next (iter (dct))' jest OK, ale 'next (dct.keys())' nie jest. – torek

+0

Ach, masz rację oczywiście, @torek. Zaktualizuję moją odpowiedź. Dzięki. – tom

8

Źródło: PEP 234, PEP 3106

Python 2 jest stosunkowo bezużyteczny dict.keys metoda istnieje ze względów historycznych. Pierwotnie dyktatury nie były możliwe do oceny.W rzeczywistości nie było czegoś takiego jak iterator; powtarzanie sekwencji działało przez wywołanie __getitem__, metody dostępu do elementu, ze wzrostem indeksów całkowitych aż do podniesienia IndexError. Aby powtórzyć klucze dyktanda, trzeba było wywołać metodę keys, aby uzyskać jawną listę kluczy i powtórzyć tę operację.

Kiedy iteratory wszedł, dicts stał iterable, bo to było wygodniejsze, szybsze i dookoła lepiej powiedzieć

for key in d: 

niż

for key in d.keys() 

to miało efekt uboczny wytwarzania d.keys() całkowicie zbędne; list(d) i iter(d) zrobili teraz wszystko, co zrobili d.keys() w czystszy, bardziej ogólny sposób. Nie mogli jednak pozbyć się keys, ponieważ tak wiele kodu już to nazwało. .

(W tym czasie dicts dostał także sposób __contains__, więc można powiedzieć key in d zamiast d.has_key(key) ten był krótszy i ładnie symetryczne for key in d; symetria jest również dlaczego Iteracja ponad DICT daje klucze zamiast (klucz , value) pairs.)

W Pythonie 3, czerpiąc inspirację z Java Collections Framework, zmieniono metody dyktowania: keys, values i items. Zamiast zwracania list, zwracają widoki oryginalnego dict. Widoki kluczowe i elementy obsługiwałyby operacje przypominające set, a wszystkie widoki byłyby owijkami wokół bazowego dicta, odzwierciedlając wszelkie zmiany w dyktowaniu. Dzięki temu ponownie użyto keys.

Powiązane problemy