2012-05-02 52 views
8

Czy istnieje sposób na wydajną iterację wartości/pozycji w słowniku, który działa zarówno w Pythonie 2, jak i Pythonie 3?Generatory do równoczesnego powtarzania słownika w Pythonie 2 i 3

W Pythonie 2, mogę napisać

for x in mydict: 
for x in mydict.iterkeys(): 
for x in mydict.viewkeys(): 
for x in mydict.itervalues(): 
for x in mydict.viewvalues(): 
for x in mydict.iteritems(): 
for x in mydict.viewitems(): 

w Pythonie 3, mam następujące możliwości:

for x in mydict: 
for x in mydict.keys(): 
for x in mydict.values(): 
for x in mydict.items(): 

Więc mogę iteracyjne nad klucze z for x in mydict i że prace zarówno w Pythonie 2 i 3. Ale czy istnieje sposób na iterację wartości i par klucz-wartość ("przedmiotów"), które działają powszechnie? Potrzebuję go do napisania kodu Pythona, który można uruchomić w obu wersjach Pythona.

(Na marginesie, inne przeszkody z iteratorów można ominąć łatwo; wziąć na przykład:

if sys.version_info.major<3: 
    from itertools import izip as zip, imap as map 

Jednakże metody słownikowe nie mogą być na nowo łatwo jak map i zip.)

Any pomysły?

+1

EDYCJA: Myślę, że chcesz powiedzieć generatory do iteracji nad słownika – jamylak

+0

@jamylak: tak, dziękuję. – Daniel

Odpowiedz

9

wartości() wersji Kolejny nieuk na odpowiedzieć

for value in (mydict[key] for key in mydict): 

lub

def dict_values(d): 
    return (mydict[key] for key in mydict) 

def dict_items(d): 
    return ((key, mydict[key]) for key in mydict) 

for value in dict_values(mydict): 
    ... 

for value in dict_items(mydict): 
    ... 

To jest dość bzdura. Można sprawdzić wersję Pythona i zamiast wrócić do generatora, powrót d.items() lub d.iteritems() odpowiednio

myślę lepsze pytanie może być, jak napisać kod python2 że dobrze współpracuje z 2to3 i generuje kod dobry Python3

+4

+1 dla ostatniego zdania. – Daenyth

+0

Jestem za propozycją gnibblera sprawdzenia wersji Pythona (raz, na początku skryptu Pythona) i zdefiniowania funkcji zwracających poprawny iterator 'd.items()' lub 'd.iteritems()'. – Daniel

0

Python2.7 ma w słowniku metodę .items, która pozwala na iterację krotek (klucz, wartość). Python3 ma takie samo API (chociaż implementacja jest inna). Czy to zadziała dla Ciebie?

+0

, ale w Python2, '.items()' tworzy tymczasową listę, której OP próbuje uniknąć. –

+0

Pytanie nie jest bardzo jasne, ale myślę, że autor chce generatorów. Zmieniłem tytuł pytania, aby to odzwierciedlić. – jamylak

+0

Nie zauważyłem tego. Dzięki. –

3

To daje generator:

for key,value in ((key,mydict[key] for key in mydict) 

Jeśli chcesz listę, użyj [] wokół wypowiedzi zamiast() na zewnątrz

+1

Łatwiejszym sposobem byłoby użycie mydict.iteritems() –

+0

To, co masz w poście, będzie działać zarówno w wersjach 2, jak i 3, ale '.iteritems() 'nie istnieje w 3. Przynajmniej nie przez tę nazwę, została przemianowana na' .items() '. –

+0

Możesz po prostu użyć powyższego rozwiązania. Wolę trzymać się z dala od list, ponieważ jeśli rozmiar słownika jest zbyt duży, uważam, że utworzenie nowej listy tworzy dużą listę. –

7

Poniższy kod działa zarówno Py2 i Py3:

def iteritems(d): 
    'Factor-out Py2-to-3 differences in dictionary item iterator methods' 
    try: 
     return d.iteritems() 
    except AttributeError: 
     return d.items() 

d = dict(red=1, blue=2, green=3) 
for k, v in iteritems(d): 
    print(k) 
    print(v) 
    print('') 

Uwaga, to rozwiązanie ma tę zaletę, że przy użyciu rodzimych iteratory zamiast toczenia własne generatory i robi własne wyszukiwań. Natywne iteratory są szybsze niż inne prezentowane rozwiązania.

Powiązane problemy