Co oznacza enumerate ()?


Odpowiedzi:


513

enumerate()Funkcja dodaje licznik do iterable.

Tak więc dla każdego elementu cursorjest tworzona krotka (counter, element); że forwiąże się pętla row_numberi rowodpowiednio.

Próbny:

>>> elements = ('foo', 'bar', 'baz')
>>> for elem in elements:
...     print elem
... 
foo
bar
baz
>>> for count, elem in enumerate(elements):
...     print count, elem
... 
0 foo
1 bar
2 baz

Domyślnie enumerate()zaczyna się od, 0ale jeśli podasz mu drugi argument liczby całkowitej, zacznie się od tej liczby:

>>> for count, elem in enumerate(elements, 42):
...     print count, elem
... 
42 foo
43 bar
44 baz

Jeśli chcesz ponownie wdrożyć enumerate()w Pythonie, oto dwa sposoby na osiągnięcie tego; jeden używa itertools.count()do zliczania, drugi ręcznie zlicza w funkcji generatora :

from itertools import count

def enumerate(it, start=0):
    # return an iterator that adds a counter to each element of it
    return zip(count(start), it)

i

def enumerate(it, start=0):
    count = start
    for elem in it:
        yield (count, elem)
        count += 1

Rzeczywistego wykonania w C jest bliżej drugi z optymalizacji ponowne wykorzystanie pojedynczego obiektu krotny dla wspólnych for i, ...rozpakowaniu obudowy i stosując standardowe wartości C całkowitą licznika dopóki licznik staje się zbyt duża, aby uniknąć stosując całkowitą obiekt Pythona (co jest bezgraniczny).


92

Jest to wbudowana funkcja, która zwraca obiekt, który można iterować. Zobacz dokumentację .

Krótko mówiąc, zapętla elementy iterowalne (takie jak lista), a także numer indeksu, połączone w krotkę:

for item in enumerate(["a", "b", "c"]):
    print item

odciski

(0, "a")
(1, "b")
(2, "c")

Jest to pomocne, jeśli chcesz zapętlić sekwencję (lub inną iterowalną rzecz), a także chcesz mieć dostępny licznik indeksów. Jeśli chcesz, aby licznik zaczynał od innej wartości (zwykle 1), możesz podać to jako drugi argument enumerate.


1
jeśli dodasz drugą zmienną item, możesz usunąć nawias: D
Abdelouahab

2
Pedantyczny: Jest to funkcja zwracająca iterator, a nie generator. Generatory to określona klasa funkcji zdefiniowanych przez użytkownika (wykorzystujących yield/ yield fromlub wyrażenia generatora, które domyślnie yield); enumeratenie jest generatorem. Dla wszystkich celów związanych z pisaniem kaczek nie ma różnicy, ale jawne sprawdzanie typów i dokumenty języka Python używają terminu „generator” tylko w jednym celu, który nie obejmuje enumerate.
ShadowRanger

22

Czytam książkę ( Effective Python ) Bretta Slatkina, który pokazuje inny sposób iteracji po liście, a także zna indeks bieżącego elementu na liście, ale sugeruje, że lepiej nie używać go, a enumeratezamiast tego używać . Wiem, że spytałeś, co oznacza wyliczenie, ale kiedy zrozumiałem następujące, zrozumiałem także, w jaki sposób enumerateiteracja po liście jest łatwiejsza (i bardziej czytelna).

list_of_letters = ['a', 'b', 'c']
for i in range(len(list_of_letters)):
    letter = list_of_letters[i]
    print (i, letter)

Dane wyjściowe to:

0 a
1 b
2 c

Ja też kiedyś coś robiłem, nawet głupszy, zanim przeczytałem o tej enumeratefunkcji.

i = 0
for n in list_of_letters:
    print (i, n)
    i += 1

Daje to samo wyjście.

Ale enumeratepo prostu muszę napisać:

list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
    print (i, letter)

20

Jak wspomnieli inni użytkownicy, enumeratejest generatorem, który dodaje przyrostowy indeks obok każdego elementu iterowalnego.

Więc jeśli masz listę powiedzenia l = ["test_1", "test_2", "test_3"]The list(enumerate(l))daje coś takiego: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Kiedy to jest przydatne? Możliwym przypadkiem użycia jest sytuacja, gdy chcesz iterować elementy i chcesz pominąć konkretny element, który znasz tylko jego indeks na liście, ale nie jego wartość (ponieważ jego wartość nie jest w tym czasie znana).

for index, value in enumerate(joint_values):
   if index == 3:
       continue

   # Do something with the other `value`

Więc twój kod czyta lepiej, ponieważ możesz również wykonywać regularne pętle for, rangeale aby uzyskać dostęp do elementów, musisz je zindeksować (tj joint_values[i].).

Chociaż inny użytkownik wspomniał o implementacji enumerateużywania zip, myślę, że bardziej czysty (ale nieco bardziej złożony) sposób bez użycia itertoolsjest następujący:

def enumerate(l, start=0):
    return zip(range(start, len(l) + start), l)

Przykład:

l = ["test_1", "test_2", "test_3"]
enumerate(l)
enumerate(l, 10)

Wynik:

[(0, „test_1”), (1, „test_2”), (2, „test_3”)]

[(10, „test_1”), (11, „test_2”), (12, „test_3”)]

Jak wspomniano w komentarzach, to podejście z zakresem nie będzie działać z dowolnymi iterowalnymi enumeratefunkcjami, jak działa funkcja oryginalna .


Inną odpowiedzią itertoolsjest to, że twoje rangepodejście działa tylko z kontenerami. enumeratewspółpracuje z dowolnymi iteracjami; jeśli chcesz iterować plik, for lineno, line in enumerate(myfile):działa, ale nie możesz tego zrobić, range(len(myfile))ponieważ długość nie jest znana, dopóki nie osiągniesz EOF.
ShadowRanger

12

Funkcja wyliczenia działa w następujący sposób:

doc = """I like movie. But I don't like the cast. The story is very nice"""
doc1 = doc.split('.')
for i in enumerate(doc1):
     print(i)

Dane wyjściowe to

(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.