Co robi for row_number, row in enumerate(cursor):
w Pythonie?
Co enumerate
znaczy w tym kontekście?
Co robi for row_number, row in enumerate(cursor):
w Pythonie?
Co enumerate
znaczy w tym kontekście?
Odpowiedzi:
enumerate()
Funkcja dodaje licznik do iterable.
Tak więc dla każdego elementu cursor
jest tworzona krotka (counter, element)
; że for
wiąże się pętla row_number
i row
odpowiednio.
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, 0
ale 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).
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
.
item
, możesz usunąć nawias: D
yield
/ yield from
lub wyrażenia generatora, które domyślnie yield
); enumerate
nie 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
.
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 enumerate
zamiast 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 enumerate
iteracja 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 enumerate
funkcji.
i = 0
for n in list_of_letters:
print (i, n)
i += 1
Daje to samo wyjście.
Ale enumerate
po prostu muszę napisać:
list_of_letters = ['a', 'b', 'c']
for i, letter in enumerate(list_of_letters):
print (i, letter)
Jak wspomnieli inni użytkownicy, enumerate
jest 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, range
ale aby uzyskać dostęp do elementów, musisz je zindeksować (tj joint_values[i]
.).
Chociaż inny użytkownik wspomniał o implementacji enumerate
używania zip
, myślę, że bardziej czysty (ale nieco bardziej złożony) sposób bez użycia itertools
jest 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 enumerate
funkcjami, jak działa funkcja oryginalna .
itertools
jest to, że twoje range
podejście działa tylko z kontenerami. enumerate
współ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.
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')