2

これを考慮してください(Python 3.3):

a=enumerate([2,3,5])
print(list(a))
print(list(a))

2回の印刷呼び出しで異なるものを印刷することを本当に期待していますか?私もしませんでした。

setリストを、、tupleまたはに置き換えても同じことが起こりますdictenumerateオブジェクトをmapまたはに置き換えた場合にも発生しますfilterが、不思議なことに、オブジェクトをに置き換えた場合は発生しませんrange

多分それは機能です。しかし、それは非常に驚くべきことであり、文書化されておらず(少なくとも私はそれについて何も見つけることができませんでした)、一貫性がありません(範囲は異なって機能します)。どう思いますか?

4

2 に答える 2

7

enumerate()他の呼び出しと同様に、イテレータを返します。イテレータは 1 回だけループできます。その後、使い果たされます。

ジェネレーター関数を使用して、そのようなイテレーターを自分で作成できます。

def somelist_generator():
    somelist = [1, 2, 3]
    while somelist:
        yield somelist.pop()

をループするsomelist_generator()と、リストsomelistが空になります。.pop()要素を削除するため、一度しか実行できません。

>>> it = somelist_generator()
>>> for i in it:
...     print(i)
... 
3
2
1
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

呼び出しは反復子next()から別の値を取得しようとします。itすでに空であるため、StopIteration例外が発生します。その例外は、取得する要素がこれ以上ないことを示しています。そのため、2 回目にイテレータから何かを取得しようとすると、空のリストになってしまいます。

>>> list(it)
[]

range()イテレータを返しません。代わりに、メモリ効率の良い一連の数値を表す範囲オブジェクトを返します。開始、終了、ストライドのみを保存する必要があり、他のすべてはこれらの 3 つのポイントから導出できます。

于 2013-01-03T10:19:51.367 に答える
2

動作はhttp://docs.python.org/3/glossary.html#term-iteratorで文書化されています

注目すべき例外の1つは、複数の反復パスを試行するコードです。...イテレータを使用してこれを試行すると、前の反復パスで使用されたものと同じ使い果たされたイテレータオブジェクトが返され、空のコンテナのように見えます。

于 2013-01-03T10:26:26.957 に答える