web-dev-qa-db-ja.com

range()がPython 3.3のジェネレーターである場合、なぜ範囲でnext()を呼び出せないのですか?

おそらく、私はウェブ上の誤った情報の犠牲になったかもしれませんが、何かを誤解しただけである可能性が高いと思います。これまでに学んだことに基づいて、range()はジェネレーターであり、ジェネレーターをイテレーターとして使用できます。ただし、このコード:

myrange = range(10)
print(next(myrange))

私にこのエラーを与えます:

TypeError: 'range' object is not an iterator

ここで何が欠けていますか?これは0を出力し、myrangeの次の値に進むことを期待していました。私はPythonが初めてなので、かなり基本的な質問に対して謝罪を受け入れてください。しかし、他のどこにも良い説明が見つかりませんでした。

64
Jeff

rangeは、不変の反復可能なオブジェクトのクラスです。それらの反復動作はlistsと比較できます:nextを直接呼び出すことはできません。 iterを使用してイテレータを取得する必要があります。

いいえ、rangeはジェネレーターではありません。

「なぜ彼らはそれを直接反復可能にしないのか」と考えるかもしれません。 rangesには、そのような方法では不可能な便利なプロパティがいくつかあります。

  • これらは不変であるため、辞書キーとして使用できます。
  • これらには、startstop、およびstep属性があります(Python 3.3)、countおよびindexメソッド。これらはinlenおよび__getitem__ 操作。
  • 同じrangeを複数回繰り返すことができます。

>>> myrange = range(1, 21, 2)
>>> myrange.start
1
>>> myrange.step
2
>>> myrange.index(17)
8
>>> myrange.index(18)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 18 is not in range
>>> it = iter(myrange)
>>> it
<range_iterator object at 0x7f504a9be960>
>>> next(it)
1
>>> next(it)
3
>>> next(it)
5
79
Oleh Prypin