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


Відповіді:


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.