すべてのイテレータはイテラブルですが、すべてのイテレータはイテレータではありません。
container.__iter__()
:
一つの方法は、反復処理サポートを提供するために、コンテナオブジェクトのために定義される必要がある:
反復可能の唯一requirementは、イテレータを返す__iter__()
メソッドを定義することです イテレータオブジェクトを返します。
iterator.__iter__()
戻りイテレータオブジェクト:これは__iter__()
方法that returns the object itselfを有する
:
iteratorは、二つの要件がありイテレータプロトコルを、従わなければなりません自体。
それは呼び出しごとに次の項目を返す__next__()
方法を持っている、そして、一度使い果たし、StopIteration
on every subsequent callを提起:
反復子の__next__()
方法はStopIteration
を上げたら、それはそうし続ける必要がありますその後の呼び出しでこのプロパティに従わない実装は壊れているとみなされます。
これらの要件は、イテレータが反復されることはありませんことを、あなたは常に反復可能なイテレータ(および定義によるので、またとない)であることを確認できることを意味iter(obj) is obj
がTrue
であることを確認することにより:
def is_unrepeatable(obj):
return iter(obj) is obj
ただし、の場合、繰り返し可能性の唯一の要件は、iter(obj)
がの一部を返すためです。イテレータは、できません。はがであることを証明しています。 iterableは__iter__()
メソッドを定義して、呼び出されるたびに異なる動作を持つイテレータを返すことができます。たとえば、最初に呼び出されたときにその要素を反復するイテレータを返すことができますが、その後の呼び出しでは直ちにStopIteration
。
この動作は奇妙な(迷惑な)ものですが、禁止されていません。ここでは、イテレータではない非反復反復可能なクラスの例です:
class Unrepeatable:
def __init__(self, iterable):
self.iterable = iterable
self.exhausted = False
def __iter__(self):
if self.exhausted:
return
else:
self.exhausted = True
yield from self.iterable
>>> x = Unrepeatable([1,2,3])
>>> list(x)
[1, 2, 3]
>>> list(x)
[]
>>> iter(x) is x
False
>>>
私はひどく行儀な「偽の反復子」と呼ぶことを躊躇しないだろう、と私ができますあなたが野生のものを見つけることができる状況を考えていますが、上記のように、それは可能です。
さらに進んでください:病理学的な例を思い浮かべるのは自明ですが、実際には「iter(obj)is obj'<=> obj is reiterable」と仮定するのは安全です。この非常に問題の核心のpython開発者によるこの[discussion](https://mail.python.org/pipermail/python-ideas/2013-September/023241.html)を見てください。私は無駄でも無意味でもない反復不可能で反復不可能な反復可能な例を見ていません。 –
@shadydog:少なくともPython 2.7では、 'urllib.urlopen'は実際の反例です。これは 'iter(obj)is obj'を持つオブジェクトを返しますが、ファイルのようなワンショット反復動作を伴います。私はPython 3の同等物が同じように動作するかどうかはわかりません。 'iter(x)is iter(x)'は 'urllib.urlopen'をキャッチするやや信頼性の高いチェックです。誰もが実際に使っていることで失敗するものは分かりませんが、それでもすべてを捕まえることはできません。 – user2357112