日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python generator_Python Generator漫谈

發布時間:2023/12/15 python 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python generator_Python Generator漫谈 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作為一個Python初學者, Python的格式化語法讓眾多編程小白追捧, 它的語法糖讓代碼變得簡潔易讀,它的龐大開源庫讓它在各個領域都能發揮作用. 但我時常感受到這個門檻極低的語言遠沒有表面上看起來易懂易用. 在Python的學習之路上, 我也時常迷茫于自己是否真正掌握了這門語言. Stackoverflow上有一篇帖子很好地說明了Python的進階之路, 于是我準備順著這個思路寫寫各個要點.

根據這篇帖子, Python進階之路: 從小白到大神. 其中, 前兩點分別是Discover list comprehensions 和 Discover generators(生成器). 身為小白的我, 心里暗想generators是個啥。于是,研究了一番,遂成此文。

注: 全文使用Python3.5, 標準庫.

談起Generator, 與之相關的的概念有{list, set, tuple, dict} comprehension and container

iterable

iterator

generator fuction and iterator

generator expression

接下來, 我們分別來看看這些概念:

{list, set, tuple, dict} comprehension and container

Container是存儲元素的數據結構, 一般存儲在內存中. 在Python中,常見的container包括但不限于:list, deque, …

set, …

tuple, namedtuple, …

dict, defaultdict, Counter, …

簡單舉例:

assert 1 in [1, 2, 3] # list

assert 1 in {1, 2, 3} # set

assert 1 in (1, 2, 3) # tuple

d = {1: 'foo', 2: 'bar', 3: 'qux'}

assert 1 in d # dict

特別的, String也是container. 我們可以查詢一個substring是否在string里, 如:

s = 'foobar'

assert 'foo' in s

assert 'x' not in s # string 包含所有的 substrings. 需要注意的是string并不存儲這些substrings, 只是可以如此查詢

iterable

一般說來,大部分的containers是iterable.而iterable不限于containers,還包括像文件.

iterable是實現了__iter__()方法的對象.該方法返回的是的一個iterator對象.其中,iterator的目的是返回所有元素.來看例子:

from collections import Iterable, Iterator

x = [1, 2, 3]

y = iter(x)

z = iter(x)

next(y)

Out: 1

next(y)

Out: 2

next(z)

Out: 1

next(z)

Out: 2

type(x)

Out: list

isinstance(x, Iterable)

Out: True

type(y)

Out: list_iterator

isinstance(y, Iterable)

Out: True

可以看出, x是list, 也是iterable. y和z都是x的返回值, 也就是iterators, 互相獨立. iterators通過___next___()這個方法返回元素,每執行一次, 返回一個元素. 值得注意的是,y作為iterable的實例, 它也是iterator. iterable是一個比iterator更大的概念.

import dis

x = [1, 2, 3]

dis.dis('for _ in x: pass')

1 0 SETUP_LOOP 14 (to 17)

3 LOAD_NAME 0 (x)

6 GET_ITER

>> 7 FOR_ITER 6 (to 16)

10 STORE_NAME 1 (_)

13 JUMP_ABSOLUTE 7

>> 16 POP_BLOCK

>> 17 LOAD_CONST 0 (None)

20 RETURN_VALUE

更深入的, 我們可以明顯看出在for循環中, Python每次都是調用FOR_ITER這個指令實現了讀取下一個next()的功能, 也就是說, for循環中,首先利用GET_ITER得到x的返回值, 一個iterator. 再通過FOR_ITER得到其中的元素. 如此實現了循環的功能.

iterator

那么什么是iterator? 就像之前我們提到的, iterator可以通過調用__next___()生成下一個值. 我們也可以說有__next___()這個方法的都可以是iterator. 這與它如何生成值無關. 我們具體看一個例子:

from itertools import islice

class seq:

def __init__(self):

self.gap = 2

self.curr = 1

def __iter__(self):

return self

def __next__(self):

value = self.curr

self.curr += self.gap

return value

f = seq()

list(islice(f, 0, 10))

Out: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

以上, 我們構建了一個等差數列, 差為2. 其中, f既是iterable(因為iter方法), 也是iterator(因為有next方法).

對于iterator, next方法做的兩件事是:更新iterator的狀態,到下次調用;

返回當前調用結果, eg: return value.

generator function and iterator

Ok. 終于到了本文的正題 generator. 首先下定義, generator是返回generator iterator的function(函數). 具體來說, 它可以讓你更優雅的實現iterator, 而不用寫帶有__iter__() 和 __next__() 的類. 繼續以上面那個等差數列為例, 我們看看generator如何的優雅的完成它:

def seq():

gap, curr = 2, 1

while True:

yield curr

curr = curr + gap

f = seq()

list(islice(f, 0, 10))

Out: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

以上, 我們看到了讓它如此優雅的原因 yield.

讓我們看看這段code是如何運行的,

首先, seq是一個Python程序, 它返回的是iterator. 當 f = seq() 被調用, generator 會準備好返回. 但這時沒有執行任何代碼.

接下來, 這個generator實例在islice()中被使用. 仍然沒有執行代碼. 然后, list()開始建立list. 為了得到list的元素, list()開始調用islice()的next()方法抓取元素, 也就是要在 f 函數中取元素.

記住每次只生成一個元素. 這是代碼開始運行到 gap, curr = 2, 1 初始化變量. 接著進入始終為真的循環, 到了yield語句. 它做兩件事: 1.暫停, 并更新狀態到下一次yield, 2. 返回當前結果, 也就是curr值, 1. 這個值接著被傳到了islice(), 最后加到list中. list現在是 [1].

list()繼續要下一個值. 暫停的 f 函數繼續運行下一個語句curr + gap. curr 現在是2. 繼續進入下一個while循環, 遇到 yield. 同樣的, yield做兩件事: 1.暫停下來調整狀態; 2. 返回值2. 值返回到list, list 等于 [1, 2].

如此循環直到list取完10個元素. 特別的, 在第11次去值, islice()會有exception: StopIteration. 告訴list已經取值結束.

generator expression

generator expression是Python的另一種generator. 相信大家都用過list expression, 比如生成一列數的平方:

numbers = [1, 2, 3, 4, 5, 6]

[x ** 2 for x in numbers]

[1, 4, 9, 16, 25, 36]

generator expression很類似, 比如

squares_list = (x * x for x in numbers)

squares_list

at 0x10435eaf0>

next(squares_list)

Out: 1

list(squares_list)

Out: [4, 9, 16, 25, 36]

以上, 不再累述.

Summary

下圖說明了各個概念之間的關系,

最后,談談為什么要使用generators. 它能幫你實現更優雅的代碼, 減少中間變量和不必要的數據結構,從而代碼量, 節省內存空間和運算性能.

針對一個循環代碼,

def something():

result = []

for ... in ...:

result.append(x)

return result

你可以做這樣的轉換

def iter_something():

for ... in ...:

yield x

感謝閱讀,歡迎大家修改指正.

本文作者:Early Kid

更多內容,請訪問:BitTiger.io, 掃描下面二維碼,關注微信公眾賬號“論碼農的自我修養”

總結

以上是生活随笔為你收集整理的python generator_Python Generator漫谈的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。