ホームページ  >  記事  >  バックエンド開発  >  Python ジェネレーターとイテレーターの違い

Python ジェネレーターとイテレーターの違い

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼オリジナル
2019-06-24 13:26:313550ブラウズ

リスト、文字列、タプル、辞書などのコンテナ オブジェクトの場合、for ループを使用して走査すると非常に便利です。 iter() 関数は、for ステートメントのバックグラウンドでコンテナー オブジェクトに対して呼び出されます。 iter() は Python の組み込み関数です。 iter() 関数は、コンテナ内の要素に 1 つずつアクセスする next() メソッドを定義するイテレータ オブジェクトを返します。 next() も Python の組み込み関数です。後続の要素がない場合、next() は StopIteration 例外をスローして、ループの終了を for ステートメントに通知します。

Python ジェネレーターとイテレーターの違い

Iterator

Iterator は、イテレータで next() 関数を使用すると、イテレータは記録された位置の次の位置にあるデータを返します。実際、 next() 関数を使用する場合、反復子オブジェクトの _next_ メソッドが呼び出されます (Python3 ではオブジェクトの _next_ メソッド、Python2 ではオブジェクトの next() メソッド)。したがって、イテレータを構築したい場合は、その _next_ メソッドを実装する必要があります。しかし、これだけでは十分ではありません。Python ではイテレータ自体も反復可能である必要があるため、イテレータの _iter_ メソッドも実装する必要があります。また、_iter_ メソッドはイテレータを返します。イテレータ自体はイテレータであるため、反復の _iter_ メソッドデバイスは自動的に戻ることができます。

いくつかの用語の説明:

1、反復子プロトコル: オブジェクトは、反復内の次の項目を返す next() メソッドを提供する必要があります。 StopIteration 例外が発生して反復が終了します。

2、反復可能オブジェクト: 反復子プロトコル オブジェクトを実装します。 List、tuple、dict はすべて Iterable (反復可能オブジェクト) ですが、Iterator (反復子オブジェクト) ではありません。ただし、組み込み関数 iter() を使用して、これらを Iterable (反復可能なオブジェクト) に変換できます。
3. Iterable ループの for 項目の本質は、まず iter() 関数を通じて反復可能オブジェクト Iterable のイテレータを取得し、次に取得したイテレータに対して next() メソッドを継続的に呼び出して次の値を取得することです。 item の場合、StopIteration 例外が発生するとループは終了します。

関連する推奨事項: 「

Python ビデオ チュートリアル

Python 独自のコンテナ オブジェクトのケース:

# 随便定义一个list
listArray=[1,2,3]
# 使用iter()函数
iterName=iter(listArray)
print(iterName)
# 结果如下:是一个列表list的迭代器
# <list_iterator object at 0x0000017B0D984278>
 
print(next(iterName))
print(next(iterName))
print(next(iterName))
print(next(iterName))#没有迭代到下一个元素,直接抛出异常
# 1
# 2
# 3
# Traceback (most recent call last):
# File "Test07.py", line 32, in <module>
# StopIteration

Python の 1 つは _iter_ メソッドとクラス オブジェクトを実装します_next_ メソッドの _iter_( self) メソッドが定義されており、このメソッドは、for ループが走査してイテレータを返すときに iter() によって呼び出されます。これは、トラバース時に Python 組み込み関数 iter() が直接呼び出され、 iter() が _iter_(self) を呼び出してオブジェクトのイテレータを取得するためです。イテレータを使用すると、要素を 1 つずつたどることができます。 1 つずつトラバースする場合、組み込みの next() 関数を使用して、オブジェクトの _next_(self) メソッドを呼び出して反復子オブジェクトをトラバースすることもできます。したがって、_iter_(self) と _next_(self) という 2 つのメソッドを実装する必要があります。

そして、_next_(self) メソッドが実装されているため、_iter_(self) を実装する場合は、self を直接返すだけです。

要約は次のとおりです:


カスタム コンテナ オブジェクトをループする場合、Python 組み込み関数 iter() を使用して、コンテナー オブジェクトの _iter_(self) を呼び出します。走査されたオブジェクトを取得して反復子を取得し、ループはこの反復子で next() を使用して反復子オブジェクトの _next_(self) を呼び出します。


注: _iter_(self) は 1 回だけ呼び出され、_next_(self) は StopIteration 例外が発生するまで n 回呼び出されます。


ジェネレーター

関数: 遅延操作。つまり、結果はすぐにではなく、必要なときに生成されます。

注:

ジェネレーターは 1 回のみ横断できます。

Generator は特殊なタイプのイテレータです。 #########分類:######

第一类:生成器函数:还是使用 def 定义函数,但是,使用yield而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。

# 菲波那切数列
def Fib(max):
 n, a, b = 0, 0, 1
 while n < max:
  yield b
  a, b = b, a + b
  n = n + 1
 return &#39;亲!没有数据了...&#39;
# 调用方法,生成出10个数来
f=Fib(10)
# 使用一个循环捕获最后return 返回的值,保存在异常StopIteration的value中
while True:
 try:
  x=next(f)
  print("f:",x)
 except StopIteration as e:
  print("生成器最后的返回值是:",e.value)
  break

第二类:生成器表达式:类似于列表推导,只不过是把一对大括号[]变换为一对小括号()。但是,生成器表达式是按需产生一个生成器结果对象,要想拿到每一个元素,就需要循环遍历。

如下案例加以说明:   

# 一个列表
xiaoke=[2,3,4,5]
# 生成器generator,类似于list,但是是把[]改为()
gen=(a for a in xiaoke)
for i in gen:
 print(i)
#结果是:
2
3
4
5
# 为什么要使用生成器?因为效率。
# 使用生成器表达式取代列表推导式可以同时节省 cpu 和 内存(RAM)。
# 如果你构造一个列表(list)的目的仅仅是传递给别的函数,
# 比如 传递给tuple()或者set(), 那就用生成器表达式替代吧! 
#本案例是直接把列表转化为元组
kk=tuple(a for a in xiaoke)
print(kk)
#结果是:
(2, 3, 4, 5) 
# python内置的一些函数,可以识别这是生成器表达式,外面有一对小括号,就是生成器
result1=sum(a for a in range(3))
print(result1)
# 列表推导式
result2=sum([a for a in range(3)])
print(result2)

区别:

生成器能做到迭代器能做的所有事,而且因为自动创建了 iter()和 next()方法,生成器显得特别简洁,而且生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。

以上がPython ジェネレーターとイテレーターの違いの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。