Python の入門から実践まで: ファンクション ジェネレータ

目次

1. yield キーワード

二、利回り式の適用

三、三項式、リスト生成、ジェネレータ式

3.1 三項式

3.2 リスト生成

3.3 ジェネレータ式


1. yield キーワード

関数本体にyield キーワードが含まれている場合、関数を再度呼び出しても関数本体のコードは実行されず、取得される戻り値はジェネレータ オブジェクトです。

>>> def my_range(start,stop,step=1):
...     print('start...')
...     while start < stop:
...         yield start
...         start+=step
...     print('end...')
... 
>>> g=my_range(0,3)
>>> g
<generator object my_range at 0x104105678>

 ジェネレーターには _iter_ および _next_ メソッドが組み込まれているため、ジェネレーター自体がセレクターです。

>>> g.__iter__
<method-wrapper '__iter__' of generator object at 0x1037d2af0>
>>> g.__next__
<method-wrapper '__next__' of generator object at 0x1037d2af0>

>>> next(g) # 触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
start...
0
>>> next(g) # 再次调用next(g),函数从上次暂停的位置继续执行,直到重新遇到yield...
1
>>> next(g) # 周而复始...
2
>>> next(g) # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
end...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

 ジェネレーター オブジェクトはイテレーターに属しているため、次のように for ループ選択を使用できる必要があります。

yield キーワードを使用すると、カスタム セレクターを実装できます。Yield は値を返すために使用できますが、return とは異なり、関数は return に遭遇すると終了し、yield は関数の実行状態を保存し、関数を一時停止して複数の値を返すことができます

二、利回り式の適用

yield は関数内の式の形式を取ることができます

>>> def eater():
...     print('Ready to eat')
...     while True:
...         food=yield
...         print('get the food: %s, and start to eat' %food)
... 

 関数を取得できるジェネレーター オブジェクトは、次のように関数本体の送信値のままです。

>>> g=eater() # 得到生成器对象
>>> g
<generator object eater at 0x101b6e2b0>
>>> next(g) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值
Ready to eat
>>> g.send('包子')
get the food: 包子, and start to eat
>>> g.send('鸡腿')
get the food: 鸡腿, and start to eat

式の形式のyieldの場合、ジェネレーターオブジェクトを事前に一度初期化する必要があるため、関数は food=yield の位置で中断され、 g.send0 メソッドを呼び出して関数本体の値を渡すのを待ちます。 g.send(None) は next( g )と同等です。 

次のように、すべての式フォームyieldに対応するジェネレーターの初期化を完了するデコレーターを書くことができます。

def init(func):
    def wrapper(*args,**kwargs):
        g=func(*args,**kwargs) #得到生成器(不会立刻有返回值)
        next(g)
        return g
    return wrapper
 
@init
def eater():
    print('Ready to eat')
    while True:
        food=yield
        print('get the food: %s, and start to eat' %food)

次のように、式形式のyieldを使用して、複数の値を返すこともできます。つまり、変数名=収率値の形式です。

>>> def eater():
...     print('Ready to eat')
...     food_list=[]
...     while True:
...         food=yield food_list
...         food_list.append(food)
... 
>>> e=eater()
>>> next(e)
Ready to eat
[]
>>> e.send('蒸羊羔')
['蒸羊羔']
>>> e.send('蒸熊掌')
['蒸羊羔', '蒸熊掌']
>>> e.send('蒸鹿尾儿')
['蒸羊羔', '蒸熊掌', '蒸鹿尾儿']

三、三項式、リスト生成、ジェネレータ式

3.1 三項式

res = 条件成立时返回的值 if 条件 else 条件不成立时返回的值

3.2 リスト生成

もちろん、リストの他に辞書もあります. () はタプルを生成するのではなく、ジェネレータを生成することに注意してください!

egg_list=['鸡蛋%s' %i for i in range(10)]

3.3 ジェネレータ式

ジェネレーターオブジェクトを作成するには2つの方法があり、1つはyieldキーワードで関数を呼び出す方法、もう1つはジェネレーター式で、リスト生成と同じ文法形式で、口を()に置き換えるだけです。つまり:

>>> [x*x for x in range(3)]
[0, 1, 4]
>>> g=(x*x for x in range(3))
>>> g
<generator object <genexpr> at 0x101be0ba0>

リスト生成と比較して、ジェネレーター式の利点は当然、メモリを節約できることです (一度にメモリ内に生成される値は 1 つだけです)。

>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g) #抛出异常StopIteration

大きなファイルのバイト数を読み取りたい場合は、ジェネレータ式に基づいて実行する必要があります

with open('db.txt','rb') as f:
    nums=(len(line) for line in f)
    total_size=sum(nums) # 依次执行next(nums),然后累加到一起得到结果=

おすすめ

転載: blog.csdn.net/weixin_43507744/article/details/126571993