1. 程式人生 > 實用技巧 >yield基礎用法

yield基礎用法

yield 是產出的意思,就是返回一個值,這一點有點像return,但是不會結束函式的執行。那它什麼時候繼續執行呢?等待下一次迭代器被呼叫時候返回上次中斷的地方,
利用這個特性可以實現range函式:

def my_range(max_num):
    i = 0
    while i < max_num:
        yield i  # 從此出產出i,下次呼叫時,從這裡繼續
        i = i + 1


for v in my_range(10):  # 帶有yield 的函式呼叫後是個生成器物件,可迭代的
    print(v)

輸出:

0
1
2
3
4
5
6
7
8
9

使用內建next方法可以呼叫生成器,可以執行到下一個yield,還可以使用生成器自帶的send方法呼叫它,並且還可以往函式內部傳值:

def f1():
    i = 0
    while 1:
        x = yield i
        print(f"x is {x}")


gen = f1()
next(gen)  # 預啟用生成器

gen.send('hh')  # 傳送的字串賦值給了 f1函式中的x,也就是yield的賦值語句

輸出:

x is hh

貌似沒啥用,可以用這個寫一個計算平均值的程式,每次使用send傳送給生成器一個數字,生成器返回所有數字的平均值:

def average():
    count = 0
    total = 0
    ave = None
    while 1:
        new_num = yield ave
        count = count + 1
        total = total + new_num
        ave = total / count


gen = average()
gen.send(None)

print(gen.send(1))
print(gen.send(2))
print(gen.send(3))

輸出:

1.0
1.5
2.0

用一個yield 呼叫另外一個yiled會返回什麼呢?

def f1():
    yield 100


def f2():
    yield f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))


輸出:

<generator object f1 at 0x10a855650>

輸出f1的生成器,呼叫完f1() ,生成一個生成器然後在f2裡面被yield出去了,那能不能獲取f1生成器中的內容yield出去?可能要這麼寫:

def f1():
    yield 100


def f2():
    yield next(f1())


if __name__ == '__main__':
    gen = f2()
    print(next(gen))

輸出:

100

它還提供了一種專用的方法, yield from:

def f1():
    yield 100


def f2():
    yield from f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))

yield from 可以yield別的生成器的內容,有人把 帶yield from的生成器叫委託生成器,真正的生成器叫子生成器,而且還可以通過委託生成器呼叫子生成器:

def f1():
    x = yield 100
    print(f"x is {x}")


def f2():
    yield from f1()


if __name__ == '__main__':
    gen = f2()
    print(next(gen))
    gen.send('hhh')  # 實際上傳送給 f1的生成器了

輸出:

Traceback (most recent call last):
  File "/Users/wuhf/PycharmProjects/cookdata/cookdata/web/test/run_yield6.py", line 13, in <module>
    gen.send('hhh')
StopIteration
100
x is hhh