2013-08-31 9 views
50

Próbuję dostępu elementu A dict_key przez jego indeksie:Dostęp do elementu dict_keys przez indeks w Python3

test = {'foo': 'bar', 'hello': 'world'} 
keys = test.keys() # dict_keys object 

keys.index(0) 
AttributeError: 'dict_keys' object has no attribute 'index' 

Chcę dostać foo.

samo:

keys[0] 
TypeError: 'dict_keys' object does not support indexing 

Jak mogę to zrobić?

+6

W py3.x 'dict.keys()' zwraca zestaw podobny do widoku obiektu, a nie do listy (tak, indeksowanie nie jest możliwe). Użyj 'keys = list (test)' –

+0

kiedy robię listę (coś_decydowania), kolejność krotek jest losowa: przykład: list ({'foo': 'bar', 'hello': 'world'}) może zwrócić : lista (foo, cześć) lub lista (cześć, foo), dlaczego jest to losowe? – fj123x

+1

[Dicts nie ma żadnego zamówienia] (http://stackoverflow.com/questions/526125/why-is-python-ordering-my-dictionary-like-so). (Użyj 'collections.OrderedDict' jeśli chcesz zamówione klucze) –

Odpowiedz

64

połączeń list() w słowniku Zamiast:

keys = list(test) 

W Pythonie 3, metoda dict.keys() zwraca dictionary view object, który działa jako zestaw. Iteracja nad słowniku bezpośrednio daje również klucze, więc obracając słownika w wynikach lista w postaci listy wszystkich kluczy:

>>> test = {'foo': 'bar', 'hello': 'world'} 
>>> list(test) 
['foo', 'hello'] 
>>> list(test)[0] 
'foo' 
+2

[ Uważaj na listę (dict.keys()) w Pythonie 3 - Blog Labix] (http://blog.labix.org/2008/06/27/watch-out-for-listdictkeys-in-python-3) wyraźnie wyjaśnia, czym jest problem, nie zapewniając rozwiązania. To jest doskonałe! –

+0

@BrandonBradley: ogólnie rzecz biorąc: poleganie na pewnych akcjach będących atomami to i tak zły pomysł, ponieważ Python jest tak dynamiczny. Twój kod może być łatwo przekazany podklasą 'dict', na przykład, gdzie' .keys() 'jest obsługiwane w kodzie Pythona (np. Może nastąpić zmiana wątku). –

25

Nie pełnej odpowiedzi, ale być może użyteczną wskazówkę. Jeśli jest naprawdę pierwsza pozycja chcesz *, a następnie

next(iter(q)) 

jest znacznie szybsze niż

list(q)[0] 

dla dużych dicts, ponieważ cała sprawa nie musi być przechowywany w pamięci.

Dla 10 000 000 pozycji okazało się, że jest prawie 40 000 razy szybsza.

* Pierwszy element w przypadku, gdy dict jest tylko pseudolosowym elementem przed Python 3.6 (po tym czasie jest zamówiony w standardowej implementacji, chociaż nie zaleca się polegania na nim).

+0

To zawsze był jeden z moich największych problemów ze staniem się iteratorami w Py3. Jest zdecydowanie bardziej wydajny, ale wiele przypadków użycia staje się "nieczystych" i skomplikowane bez powodu. Na przykład, dlaczego nie mogą po prostu obsługiwać indeksowania w iteratorze, niekoniecznie tracąc wydajność? –

Powiązane problemy