web-dev-qa-db-ja.com

Pythonリストのイテレータの振る舞いとnext(イテレータ)

検討してください:

>>> lst = iter([1,2,3])
>>> next(lst)
1
>>> next(lst)
2

したがって、イテレータを進めることは、予想通り、その同じオブジェクトを変更することによって処理されます。

そうだ、私は期待するだろう:

a = iter(list(range(10)))
for i in a:
   print(i)
   next(a)

2番目の要素ごとにスキップするには、nextの呼び出しでイテレータを1回進め、次にループによって行われた暗黙の呼び出しで2回目の繰り返しを行い、この2番目の呼び出しの結果をiに割り当てます。

そうではありません。ループは、リスト内の項目をall何もスキップせずに表示します。

私の最初の考えは、ループが渡されるものに対してiterを呼び出すのでこれが起こるかもしれないということです、そして、これは独立したイテレータを与えるかもしれません - iter(a) is aを持っているのでこれは当てはまりません。

では、どうしてnextがこの場合イテレータを進めないように見えるのでしょうか。

128
lvc

表示されるのは、反復ごとにiが出力されるのに加えて、next()の戻り値をエコーバックするインタプリタです。

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    next(a)
... 
0
1
2
3
4
5
6
7
8
9

そのため、0print(i)の出力、1next()からの戻り値、対話型インタープリタなどによってエコーされます。各繰り返しは2行が端末に書き込まれる結果になります。

next()の出力を割り当てると、期待通りに動作します。

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    _ = next(a)
... 
0
2
4
6
8

対話型インタプリタのエコーからのprint()の出力を区別するために、または--- extraの情報を出力します。

>>> a = iter(list(range(10)))
>>> for i in a:
...    print('Printing: {}'.format(i))
...    next(a)
... 
Printing: 0
1
Printing: 2
3
Printing: 4
5
Printing: 6
7
Printing: 8
9

言い換えれば、next()は期待通りに動作していますが、それは対話式インタプリタによってエコーされて、イテレータから次の値を返すので、あなたはループがそれ自身のイテレータコピーをどうにか持っていると信じます。

173
Martijn Pieters

何が起きているのかというと、next(a)はaの次の値を返します。これは影響を受けないためコンソールに表示されます。

できることは、この値を持つ変数に影響を与えることです。

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    b=next(a)
...
0
2
4
6
8
12
njzk2

既存の答えは、コード例で本質的に不可解なことを間接的に示しているだけなので、やや紛らわしいと思います。both * "print i"と "next(a)"はそれらの結果を引き起こしています。印刷されます。

それらは元のシーケンスの交互の要素を印刷しているので、そして "next(a)"ステートメントが印刷していることは予想外であるので、 "print i"ステートメントがすべての値を印刷しているように見えます。

その意味で、 "next(a)"の結果を変数に代入するとその結果の出力が抑制されるので、 "i"ループ変数の代わりの値だけが出力されることがより明確になります。同様に、 "print"ステートメントにもっと独特の何かを発行させることも同様にそれを明確にします。

(既存の回答の1つは、その回答がサンプルコードをブロックとして評価しているため、インタプリタが "next(a)"の中間値を報告していないため、他の回答に反論します。)

一般的に、質問に答える際の最も厄介なことは、あなたが答えを知ったら明らかになることについて明白であるということです。それはとらえどころのないことができます。あなたがそれらを理解したら同様に答えを批評すること。それは面白い...

7
klm

あなたのPython /コンピュータに何か問題があります。

a = iter(list(range(10)))
for i in a:
   print(i)
   next(a)

>>> 
0
2
4
6
8

期待通りに動作します。

Python 2.7とPython 3+でテスト済み。両方で正常に動作します

2
Inbar Rose

関数として呼び出された場合、それはあなたが望む方法で振る舞います:

>>> def test():
...     a = iter(list(range(10)))
...     for i in a:
...         print(i)
...         next(a)
... 
>>> test()
0
2
4
6
8
1
burmer

まだ理解していない人のために。

>>> a = iter(list(range(10)))
>>> for i in a:
...    print(i)
...    next(a)
... 
0 # print(i) printed this
1 # next(a) printed this
2 # print(i) printed this
3 # next(a) printed this
4 # print(i) printed this
5 # next(a) printed this
6 # print(i) printed this
7 # next(a) printed this
8 # print(i) printed this
9 # next(a) printed this

他の人がすでに言ったように、nextは期待通りにイテレータを1増加させます。戻り値を変数に代入しても、その動作は魔法のように変わりません。

1
Wesley