Що означає перерахування ()?


Відповіді:


513

enumerate()Функція додає лічильник на итератор.

Отже, для кожного елемента в cursor, виробляється кортеж з (counter, element); то forпетля пов'язує , що row_numberі row, відповідно.

Демонстрація:

>>> 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

За замовчуванням enumerate()починає рахувати, 0але якщо ви дасте йому другий цілий аргумент, він почне починати з цього числа:

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

Якщо ви хотіли повторно реалізувати enumerate()в Python, ось два способи досягти цього; один використовує itertools.count()для підрахунку, інший вручну підраховує функцію генератора :

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)

і

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

Фактична реалізація в C ближче до останнього, з оптимізаціями повторно використовувати один об'єкт кортежу для загальної for i, ...розпакування справи і з використанням стандартного З цілочисельного значення для лічильника , поки лічильник не стає занадто великим , щоб уникнути використання целочисленного об'єкта Python (який є необмежений).


92

Це вбудована функція, яка повертає об'єкт, який можна повторити. Дивіться документацію .

Коротше кажучи, вона перетинає елементи перегляду (як список), а також номер індексу, об'єднаний у кортеж:

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

відбитки

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

Це корисно, якщо ви хочете перевести цикл на послідовність (або іншу річ), а також хочете мати лічильник індексів. Якщо ви хочете, щоб лічильник починався з якогось іншого значення (зазвичай 1), ви можете надати це як другий аргумент enumerate.


1
якщо ви додасте другу змінну, itemви можете видалити круглі дужки: D
Abdelouahab

2
Педантичний: це функція, що повертає ітератор, а не генератор. Генератори - це специфічний клас визначених користувачем функцій (використання yield/ yield fromабо вирази генератора, що неявно yield); enumerateне генератор. Для всіх цілей, пов’язаних із набором качок, немає різниці, але явна перевірка типу та документи мови Python використовують лише термін "генератор" для однієї мети, який не охоплює enumerate.
ShadowRanger

22

Я читаю книгу ( Ефективний Python ) Бретта Слаткіна, і він показує інший спосіб перебору списку, а також знаю індекс поточного елемента в списку, але він припускає, що краще не використовувати його, а використовувати enumerateзамість нього. Я знаю, що ви запитали, що означає перерахування, але коли я зрозумів наступне, я також зрозумів, як enumerateспростити перегляд списку, знаючи індекс поточного елемента простішим (і читабельніше).

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

Вихід:

0 a
1 b
2 c

Я також раніше щось робив, навіть дурніше, перш ніж читати про enumerateфункцію.

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

Це дає такий же вихід.

Але з цим enumerateя просто повинен написати:

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

20

Як згадували інші користувачі, enumerateце генератор, який додає інкрементний індекс поруч із кожним елементом, який можна повторити.

Так що якщо у вас є список сказати l = ["test_1", "test_2", "test_3"], то list(enumerate(l))дасть вам що - щось на зразок цього: [(0, 'test_1'), (1, 'test_2'), (2, 'test_3')].

Тепер, коли це корисно? Можливий випадок використання, коли ви хочете перебрати елементи, і ви хочете пропустити певний елемент, який ви знаєте лише його індекс у списку, але не його значення (тому що його значення наразі невідоме).

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

   # Do something with the other `value`

Таким чином, ваш код читається краще, тому що ви також можете зробити звичайний цикл за допомогою, rangeале потім отримати доступ до елементів, які вам потрібно проіндексувати (тобто joint_values[i]).

Хоча інший користувач згадав про реалізацію enumerateвикористання zip, я думаю, що більш чистим (але трохи складнішим) способом без використання itertoolsє наступний:

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

Приклад:

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

Вихід:

[(0, 'test_1'), (1, 'test_2'), (2, 'test_3')]

[(10, 'test_1'), (11, 'test_2'), (12, 'test_3')]

Як зазначалося в коментарях, цей підхід з діапазоном не працюватиме з довільними ітерабелями, як це enumerateробить оригінальна функція.


Причина, яку згадує інша відповідь, itertoolsполягає в тому, що ваш rangeпідхід працює лише з контейнерами. enumerateпрацює з довільними ітерабелями; якщо ви хочете повторити файл, for lineno, line in enumerate(myfile):працює, але ви не можете цього зробити, range(len(myfile))оскільки довжина не відома, поки ви не досягнете EOF.
ShadowRanger

12

Функція перерахування працює наступним чином:

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)

Вихід є

(0, 'I like movie')
(1, " But I don't like the cast")
(2, ' The story is very nice')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.