enumerate()はどういう意味ですか?


回答:


513

このenumerate()関数は、イテラブルにカウンターを追加します。

したがって、の要素ごとcursorに、タプルがで生成され(counter, element)ます。forループが結合することrow_numberrow、それぞれ。

デモ:

>>> 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が、2番目の整数引数を指定すると、代わりにその数値から開始されます。

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

enumerate()Pythonで再実装する場合、これを実現する2つの方法があります。1つitertools.count()はカウントを行うために使用し、もう1つはジェネレータ関数で手動でカウントします

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)から開始する場合は、それを2番目の引数としてに指定できenumerateます。


1
あなたが第二の変数を追加した場合item、あなたは括弧を削除することができます:D
Abdelouahab

2
Pedantic:これはジェネレータではなく、イテレータを返す関数です。ジェネレーターは、ユーザー定義関数の特定のクラスですyield/ を使用するyield fromか、暗黙的にジェネレーター式を使用しyieldます)。enumerateジェネレータではありません。すべてのダックタイピングに関連する目的には違いはありませんが、明示的な型チェックとPython言語のドキュメントでは、「ジェネレータ」という用語を1つの目的でのみ使用しています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`

したがって、通常のforループを使用してコードを読み取ることもできますが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')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.