Pythonでの歩留まりを理解するための記事

この記事を読むのに約3.6分かかります。

Yieldは、ジェネレーターとコルチンを実装できます。ジェネレーターとは何か、コルティンとは何か、それでも理解できない場合は、見下ろし続けることができます。その機能と効果を理解している限り、概念を理解する必要はありません。

まず、英語のyieldの意味を見てください。

to produce or provide sth, for example a profit, result or crop

中国の意味:生産(作物);生産(収入、利益など);提供。

イールド実装ジェネレーター

Pythonを初めて学んだとき、yieldキーワードに出会ったとき、それは特別な種類のリターンであると理解しました。理解でき、自分で使用することはめったになかったので、深く研究しませんでした。今までは大量のデータを処理する必要があり、データのサイズはコンピューターの空きメモリーを超えていましたが、今回は歩留まりを考えています。たとえば、db2データベースを操作してデータをクエリします。データの結果が非常に大きい場合、一度にメモリに読み込みたくありません。yieldキーワードを使用してデータの行を返します。プログラムが処理されたら、次の行をフェッチします。

def read(self, sql, params=()):

 stmt = ibm_db.prepare(self.connection, sql)for index, param inenumerate(params):
  ibm_db.bind_param(stmt, index +1, param)
 ibm_db.execute(stmt)
 row = ibm_db.fetch_tuple(stmt)while row:yield row
  row = ibm_db.fetch_tuple(stmt)

キーワードyieldの使用法は、次のように理解できます。値は返されますが、プログラムは終了しません。次回、yieldの背後にあるコードは、コードがなくなるまで実行され続け、操作が終了します。ここでは、効果を確認するための簡単な例を示します。

>>> def iter_fun():...print("a")...yield1...print("b")...yield2...print("c")...yield3...>>>iter_fun()<generator object iter_fun at 0x107e372a0>>>>for i initer_fun():...print(i)...
a
1
b
2
c
3>>> x =iter_fun()>>> x.__next__()
a
1>>> x.__next__()
b
2>>> x.__next__()
c
3>>> x.__next__()Traceback(most recent call last):
 File "<stdin>", line 1,in<module>
StopIteration

上記の例から、yieldキーが自動的にプライベートメソッド__next__を生成するため、すべてのデータが取り出されてメモリに保存されることはありません。メモリスペースを節約したいだけ使用してください。

さらに、データ量が多いと、yieldの実行速度が向上します。

In [14]: def normal_fun(num):...:     result =[]...:for i inrange(0,num):...:if i%2==0:...:             result.append(i)...:return result
    ...:

In [14]: def iter_fun(num):...:for i inrange(0,num):...:if i %2==0:...:yield i
    ...:

In [15]:%time for i initer_fun(1000000): a = i
CPU times: user 97 ms, sys:2.55 ms, total:99.6 ms
Wall time:97.2 ms

In [16]:%time for i innormal_fun(1000000): a = i
CPU times: user 115 ms, sys:13.6 ms, total:129 ms
Wall time:128 ms

In [17]:%time for i innormal_fun(100000000): a = i
CPU times: user 10.8 s, sys:668 ms, total:11.4 s
Wall time:11.4 s

In [18]:%time for i initer_fun(100000000): a = i
CPU times: user 9.1 s, sys:6.49 ms, total:9.11 s
Wall time:9.12 s

上記のコードはIpython端末で実行されます。yieldを使用した関数の方が実行速度が速いことがわかります。

歩留まりは、ジェネレータを自分で実装するための最も便利な方法です。 Python言語のジェネレーターは、最も便利な機能の1つであり、あまり使用されていない機能でもあります。同様の機能があるかどうか、javaを使用している友人に尋ねました。いいえと答えました。インターネットで検索しました。これは確かに主流のプログラミング言語です。なし、したがって、Pythonのジェネレーター機能は、他の言語をPythonに変換するエンジニアの注目を集めていません。

なぜジェネレーターは非常に便利なのですか?

処理する必要のあるデータのサイズがコンピューターの使用可能なメモリーを超える場合、ジェネレーターの遅延ロード(使用時にメモリーへの読み取り)は非常に効果的です。

たとえば、ファイルを読み取るときに次の方法を使用すると、ファイルが特に大きい場合、メモリがすぐにいっぱいになる可能性があります。

withopen("file.txt","r")as reader:for line in reader.readlines():
  # do something
  pass

推奨される方法は、ファイル自体のジェネレーターを使用して、ファイルのサイズに関係なく、メモリがバーストしないようにすることです。

withopen("file.txt","r")as reader:for line in reader:
  # do something
  pass

実際、リーダーのメソッドを見ることができます。

>>> withopen("/etc/passwd","r")as reader:...dir(reader)...['_CHUNK_SIZE','__class__','__del__','__delattr__','__dict__','__dir__','__doc__','__enter__','__eq__','__exit__','__format__','__ge__','__getattribute__','__getstate__','__gt__','__hash__','__init__','__init_subclass__','__iter__','__le__','__lt__','__ne__','__new__','__next__','__reduce__','__reduce_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','_checkClosed','_checkReadable','_checkSeekable','_checkWritable','_finalizing','buffer','close','closed','detach','encoding','errors','fileno','flush','isatty','line_buffering','mode','name','newlines','read','readable','readline','readlines','reconfigure','seek','seekable','tell','truncate','writable','write','write_through','writelines']>>>

__iter__メソッドと__next__メソッドがあることがわかります。これら2つのメソッドはジェネレーターの兆候です。

ジェネレーター、イテレーター、およびイテラブルオブジェクトについて詳しく知りたい場合は、以前のツイートを読むことができます。

[ Pythonの基本シリーズ-反復可能なオブジェクト、反復子、およびジェネレーター](http://mp.weixin.qq.com/s?__biz=MzU0OTg3NzU2NA==&mid=2247483827&idx=1&sn=6a661c78b3f0db2e4c94cee1ddc3b036&chksm=fba86

[ イテレーターとジェネレーターの詳細な理解](http://mp.weixin.qq.com/s?__biz=MzU0OTg3NzU2NA==&mid=2247484255&idx=1&sn=cb340bdf3038a8d1715a89a8752c65c5&chksm=fba8610cccd3ccrebdirect4

歩留まりはコロチンを実装できます

コルチンの実現を容易にするためのasyncioおよびawaitキーワードがありますが、yieldキーワードもコルチンを実現できます。それ以前は、コルチンの実現はyieldに依存していました。

Yieldにはsendメソッドがあり、yieldの戻り値を変更できます。これは次のように使用されます。最初にコードを見てください。

In [20]: def fun():...:print("a")...:     a =yield1...:print("b")...:print("a = ",a)...:     b =yield a
 ...: print("c")...:print("b = ",b)...:

In [21]: x =fun()

In [22]: x.__next__()
a
Out[22]:1

In [23]: x.send(4)
b
a =4
Out[23]:4

In [24]: x.send(5)
c
b =5---------------------------------------------------------------------------
StopIteration                             Traceback(most recent call last)<ipython-input-24-9183f5e81876>in<module>---->1 x.send(5)

xの__next__メソッドが初めて実行されると、関数は最初のyieldまで実行され、aを出力して、値1を返します。このとき、変数aはyieldの戻り値を取得せず、aはNoneです。x.sendが実行されると(4)、aは値4を取得し、プログラムは2番目のyieldまで実行され、後続のプロセスは同じです。

この機能を使用して、呼び出された関数と通信し、プロデューサーコンシューマーモデルを実装できます。コードは次のとおりです。

import time

def consume():
 r =''while True:
  n =yield r
  if not n:returnprint('[consumer] consuming %s...'% n)
  time.sleep(1)
  r ='well received'

def produce(c):next(c)
 n =0while n <5:
  n = n +1print('[producer] producing %s...'% n)
  r = c.send(n)print('[producer] consumer return: %s'% r)
 c.close()if __name__=='__main__':
 c =consume()produce(c)

結果は次のとおりです。

[ producer] producing 1...[consumer] consuming 1...[producer] consumer return: well received
[ producer] producing 2...[consumer] consuming 2...[producer] consumer return: well received
[ producer] producing 3...[consumer] consuming 3...[producer] consumer return: well received
[ producer] producing 4...[consumer] consuming 4...[producer] consumer return: well received
[ producer] producing 5...[consumer] consuming 5...[producer] consumer return: well received

生成関数と消費関数は1つのスレッドで実行され、coroutineの関数は、sendメソッドを呼び出してsendメソッドとyieldを切り替えることで実現されます。

coroutineについて学ぶために、あなたは私の以前のつぶやきを見ることができます:

[ 定期的な研究ノート)(http://mp.weixin.qq.com/s?__biz=MzU0OTg3NzU2NA==&mid=2247483684&idx=1&sn=0a106dcbe89438b4a1d3dd77eadd2900&chksm=fba86377ccdfea6110de27f78e828cfdaacrechat

[ 並行性のためにマルチスレッドまたはコルルーチンを使用しますか? ](http://mp.weixin.qq.com/s?__biz=MzU0OTg3NzU2NA==&mid=2247484280&idx=1&sn=ad46f3ef58ee7739da7d4f98ea97134c&chksm=fba8612bccdfe83d32e78e8ee7feadd4fc4benebd

この記事に興味がある場合は、「フォロー」または「ウォッチング」のサポートを提供してください。 WeChatで「PythonNo。7」を検索し、フォローしてオリジナルの乾物を直接入手してください。

Recommended Posts

Pythonでの歩留まりを理解するための記事
Pythonでのパッケージの導入を理解する方法
Pythonで変数を理解する方法
Python | Pythonのリスト、タプル、文字列の操作を理解するための記事
Pythonでグローバル変数を理解する方法
pythonでround関数を使用する方法
Pythonでzip関数を使用する方法
pythonでformat関数を使用する方法
ダウンロードしたモジュールをpythonでインストールする方法
Pythonで正規表現を取得するための1つの記事
Pythonで型を判断するための最良の方法
pythonで番号のリストを理解する方法
IEを添付ファイルとしてPythonで保存する方法
pythonでファイルを開く方法は何ですか
pythonオブジェクトを理解する方法
pythonで円の領域を見つける方法
pythonでのwheelの使用法
pythonコードでラップする方法
Pythonで括弧を省略する方法
pythonでクラスを書く方法
pythonで数値をフィルタリングする方法
Pythonの数字は何ですか?
PythonでExcelを読む方法
Pythonのすべてがオブジェクトです
pythonでエラーを表示する方法
pythonでreturnを書く方法
Pythonのモジュールについて話す
pythonモジュールを表示する方法
pythonで変数をクリアする方法
pythonオブジェクト指向プログラミングを理解する方法
pythonでのタプルの使用法
PythonでSQLiteを使用する方法
pythonでのrbの意味を理解する
およびおよびまたはPythonでの使用方法
pythonでキャッシュファイルを削除する方法
Pythonでサードパーティモジュールを導入する方法
pythonでnull値を表す方法
Python3クローラーでのAjaxの使用
pythonでテキストファイルを保存する方法
パスワードの強度を判断するためのPython文字列
pythonでwinプログラムを書く方法
pythonでid関数を実行する方法
Pythonでサードパーティモジュールをインストールする方法
pythonでエラーをカスタムキャッチする方法
pythonでtryステートメントを書く方法
Pythonの匿名関数とは何ですか
Pythonでプライベート属性を定義する方法
Pythonでカスタムモジュールを追加する方法
インストールされているモジュールをpythonで表示する方法
Python初心者はライブラリの使い方を学びます
Pythonタイムモジュールを学ぶ方法
さまざまなシステムでのPythonopenメソッド
pythonで辞書を並べ替える方法
Python開発環境Spyderをすばやく理解する
pythonで背景音楽を追加する方法
pythonで相対パスを表す方法
Pythonはリスト内の要素をランダムにシャッフルします
pythonでのadbの機能は何ですか
Pythonのインターフェースに基づいてプログラミングする方法
Pythonはemailモジュールを使用してメールを送信します
ubuntuサーバー環境にpythonをインストールする方法