翻訳:「実用的なPythonプログラミング」06_02_Customizing_iteration

目次|前のセクション(6.1反復プロトコル)|次のセクション(6.3生産者/消費者)

6.2カスタムイテレーション

リベートウェブサイトwww.cpa5.cn

このセクションでは、ジェネレーター関数を使用して反復をカスタマイズする方法について説明します。

問題

反復モードをカスタマイズするとします。

例:カウントダウン:

>>> for x in countdown(10):
...   print(x, end=' ')
...
10 9 8 7 6 5 4 3 2 1
>>>

これを行う簡単な方法があります。

ビルダー

ジェネレーターは、反復を定義する関数です。

def countdown(n):
    while n > 0:
        yield n
        n -= 1

例:

>>> for x in countdown(10):
...   print(x, end=' ')
...
10 9 8 7 6 5 4 3 2 1
>>>

yieldジェネレーターと呼ばれる関数ステートメントの使用

ジェネレータ関数の動作は通常の関数とは異なります。ジェネレーター関数を呼び出すと、関数をすぐに実行する代わりに、ジェネレーターオブジェクトが作成されます。

def countdown(n):
    # Added a print statement
    print('Counting down from', n)
    while n > 0:
        yield n
        n -= 1
>>> x = countdown(10)
# There is NO PRINT STATEMENT
>>> x
# x is a generator object
<generator object at 0x58490>
>>>

ジェネレーター関数は__next__()、メソッドが呼び出されたときにのみ実行されます。

>>> x = countdown(10)
>>> x
<generator object at 0x58490>
>>> x.__next__()
Counting down from 10
10
>>>

yield値は生成されますが、サスペンド機能が実行されます。__next__()メソッド(resume)のとき再開する次の呼び出しのビルダー関数

>>> x.__next__()
9
>>> x.__next__()
8

ジェネレータが最後の値を返したときに、もう一度繰り返すとエラーが発生します。

>>> x.__next__()
1
>>> x.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in ? StopIteration
>>>

観察:ジェネレーター関数によって実装されるプロトコルは、リスト、タプル、辞書、およびファイルのforステートメントによって使用される基礎となるプロトコルと同じです。

運動

演習6.4:単純なジェネレーター

カスタム反復が必要な場合は、常にジェネレーター関数を検討する必要があります。ジェネレーター関数は簡単に記述できます-反復ロジックを実行するために必要な関数を作成し、yield送信値を使用します。

たとえば、ファイルの各行で一致する部分文字列を検索するジェネレータを作成するには、次のようにします。

>>> def filematch(filename, substr):
        with open(filename, 'r') as f:
            for line in f:
                if substr in line:
                    yield line

>>> for line in open('Data/portfolio.csv'):
        print(line, end='')

name,shares,price
"AA",100,32.20
"IBM",50,91.10
"CAT",150,83.44
"MSFT",200,51.23
"GE",95,40.37
"MSFT",50,65.10
"IBM",100,70.44
>>> for line in filematch('Data/portfolio.csv', 'IBM'):
        print(line, end='')

"IBM",50,91.10
"IBM",100,70.44
>>>

これは興味深いアイデアです。関数内のカスタム処理を非表示にして、関数をforループに適用できます。次の例では、より異常な状況を調査します。

演習6.5:ストリーミングデータソースを監視する

ジェネレーターは、リアルタイムのデータソース(ログファイル、株式市場のニュースなど)を監視するために使用できます。このパートでは、「ジェネレーターを使用してリアルタイムのデータソースを監視する」というアイデアを探ります。まず、以下の指示に厳密に従ってください。

Data/stocksim.py株式市場のデータを模倣するために、リアルタイムのデータが引き続きData/stocklog.csvファイルに書き込まれます。別のコマンドラインウィンドウを開き、Data/ディレクトリを入力してstocksim.pyプログラムを実行します。

bash % python3 stocksim.py

Windowsシステムを使用している場合は、stocksim.pyファイルを見つけて、ファイルをダブルクリックして実行します。次に、それをプログラム用に取っておき(その時点で実行されています)、別のコマンドラインウィンドウを開き、シミュレーションプログラムがstocksim.pyデータData/stocklog.csvファイルを書き込んでいることを確認します(翻訳:)データファイルを書き込んでいます(翻訳:Linuxシステムを使用している場合は、データディレクトリに移動し、tail -f stocklog.csvコマンドを使用して表示します)。数秒ごとに新しいテキスト行がData/stocklog.csvファイルに追加されます。同様に、プログラムをバックグラウンドで実行します-プログラムは数時間実行されます(これについては心配しないでください)。

stocksim.pyプログラムを実行した後Data/stocklog.csv、ファイルを開き、ファイルの最後に移動して、新しい出力を表示するプログラムを作成しましょうat Workディレクトリfollow.pyファイルを作成し、次のコードを入力してください。

# follow.py
import os
import time

f = open('Data/stocklog.csv')
f.seek(0, os.SEEK_END)   # Move file pointer 0 bytes from end of file

while True:
    line = f.readline()
    if line == '':
        time.sleep(0.1)   # Sleep briefly and retry
        continue
    fields = line.split(',')
    name = fields[0].strip('"')
    price = float(fields[1])
    change = float(fields[4])
    if change < 0:
        print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

follow.py プログラムを実行すると、リアルタイムの株価情報(株式相場表示)が表示されます。follow.py ログファイルtail -fコマンドを表示するUnixライクなシステムのコード

注:この例でreadline()は、使用方法は、一般に、わずかに異なる実施形態(通常はfor循環)のファイルから読み取られますこの場合、readline()endを使用して重複ファイルを検出し、新しいデータが追加されているかどうかを確認します(readline()メソッドは新しいデータまたは空の文字列を返します)。

演習6.6:ジェネレーターを使用してデータを生成する

演習6.5のコードを見ると、コードの最初の部分で数行のデータが生成さwhileれ、ステートメントの消費データの最後で循環していることがわかります。ジェネレーターの主な機能の1つは、データを生成するコードを再利用可能な関数に移動できることです。

6.5実践コードを編集して、ジェネレーター関数を介しfollow(filename)て実行ファイルを読み取るようにします。次のコードが機能するように、変更を実装してください。

>>> for line in follow('Data/stocklog.csv'):
          print(line, end='')

... Should see lines of output produced here ...

コードが次のようになるように、株価コードを変更してください。

if __name__ == '__main__':
    for line in follow('Data/stocklog.csv'):
        fields = line.split(',')
        name = fields[0].strip('"')
        price = float(fields[1])
        change = float(fields[4])
        if change < 0:
            print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

演習6.7:株式ポートフォリオを表示する

follow.pyプログラムを変更して、プログラムがストリーミング株式データを表示し、それらの株式の情報株式ポートフォリオを印刷できるようにします。例:

if __name__ == '__main__':
    import report

    portfolio = report.read_portfolio('Data/portfolio.csv')

    for line in follow('Data/stocklog.csv'):
        fields = line.split(',')
        name = fields[0].strip('"')
        price = float(fields[1])
        change = float(fields[4])
        if name in portfolio:
            print(f'{name:>10s} {price:>10.2f} {change:>10.2f}')

注:このコードを実行できるようにするにPortfolioは、クラスがin演算子をサポートしている必要があります。Portfolioクラスが__contains__()演算子を実装していることを確認するには、演習6.3を参照してください

話し合います

ここでは、興味深い反復パターン(ファイルの最後にある行の読み取り)を関数に移動します。follow()関数は、あらゆるプログラムで使用できる完全にユニバーサルなユーティリティになりました。たとえば、このfollow()関数を使用して、他のデータソースと同様に、サーバーログ、デバッグログを表示できます。

目次|前のセクション(6.1反復プロトコル)|次のセクション(6.3生産者/消費者)

注:完全な翻訳については、https://github.com/codists/practical-python-zhを参照してください

おすすめ

転載: blog.csdn.net/weixin_48967543/article/details/114924464