亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Python中關鍵字yield有什么作用?

2019-11-14 10:01:31
字體:
來源:轉載
供稿:網友

yield有什么用?

例如下面這段代碼:

def node._get_child_candidates(self, distance, min_dist, max_dist): if self._leftchild and distance - max_dist < self._median: yield self._leftchild if self._rightchild and distance + max_dist >= self._median: yield self._rightchild

下面是調用它:

result, candidates = list(), [self]while candidates: node = candidates.pop() distance = node._get_dist(obj) if distance <= max_dist and distance >= min_dist: result.extend(node._values) candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))return result

當_get_child_candidates方法被調用的時候發生了什么?是返回一個列表?還是一個元祖?它還能第二次調用嗎?后面的調用什么時候結束?

為了理解yield有什么用,首先得理解generators,而理解generators前還要理解iterables

Iterables

當你創建了一個列表,你可以一個一個的讀取它的每一項,這叫做iteration:

>>> mylist = [1, 2, 3]>>> for i in mylist:... PRint(i)123

Mylist是可迭代的.當你用列表推導式的時候,你就創建了一個列表,而這個列表也是可迭代的:

>>> mylist = [x*x for x in range(3)]>>> for i in mylist:... print(i)014

所有你可以用在for…in…語句中的都是可迭代的:比如lists,strings,files…因為這些可迭代的對象你可以隨意的讀取所以非常方便易用,但是你必須把它們的值放到內存里,當它們有很多值時就會消耗太多的內存.

Generators

生成器也是迭代器的一種,但是你只能迭代它們一次.原因很簡單,因為它們不是全部存在內存里,它們只在要調用的時候在內存里生成:

>>> mygenerator = (x*x for x in range(3))>>> for i in mygenerator:... print(i)014

生成器和迭代器的區別就是用()代替[],還有你不能用for i in mygenerator第二次調用生成器:首先計算0,然后會在內存里丟掉0去計算1,直到計算完4.

Yield

Yield的用法和關鍵字return差不多,下面的函數將會返回一個生成器:

>>> def createGenerator():... mylist = range(3)... for i in mylist:... yield i*i...>>> mygenerator = createGenerator() # 創建生成器>>> print(mygenerator) # mygenerator is an object!<generator object createGenerator at 0xb7555c34>>>> for i in mygenerator:... print(i)014

在這里這個例子好像沒什么用,不過當你的函數要返回一個非常大的集合并且你希望只讀一次的話,那么它就非常的方便了.

要理解Yield你必須先理解當你調用函數的時候,函數里的代碼并沒有運行.函數僅僅返回生成器對象,這就是它最微妙的地方:-)

然后呢,每當for語句迭代生成器的時候你的代碼才會運轉.

現在,到了最難的部分:

當for語句第一次調用函數里返回的生成器對象,函數里的代碼就開始運作,直到碰到yield,然后會返回本次循環的第一個返回值.所以下一次調用也將運行一次循環然后返回下一個值,直到沒有值可以返回.

一旦函數運行并沒有碰到yeild語句就認為生成器已經為空了.原因有可能是循環結束或者沒有滿足if/else之類的.

對于你的代碼的解釋

生成器:

# 這里你創建node方法的對象將會返回一個生成器def node._get_child_candidates(self, distance, min_dist, max_dist): # 這里的代碼你每次使用生成器對象的時候將會調用 if self._leftchild and distance - max_dist < self._median: yield self._leftchild if self._rightchild and distance + max_dist >= self._median: yield self._rightchild # 如果代碼運行到這里,生成器就被認為變成了空的調用:# 創建空列表和一個當前對象索引的列表result, candidates = list(), [self]# 在candidates上進行循環(在開始只保含一個元素)while candidates: # 獲得最后一個condidate然后從列表里刪除 node = candidates.pop() # 獲取obj和candidate的distance distance = node._get_dist(obj) # 如果distance何時將會填入result if distance <= max_dist and distance >= min_dist: result.extend(node._values) candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))return result

這段代碼有幾個有意思的地方:

一般的時候我們會在循環迭代一個列表的同時在列表中添加元素:-)盡管在有限循環里結束多少有一些危險,但也不失為一個簡單的方法去遍歷嵌套的數據.在這里candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))將遍歷生成器的每一個值,但是while循環中的condidates將不再保存已經遍歷過的生成器對象,也就是說添加進condidates的生成器對象只會遍歷一遍。

extend()是一個列表對象的方法,它可以把一個迭代對象添加進列表.

我們經常這么用:

>>> a = [1, 2]>>> b = [3, 4]>>> a.extend(b)>>> print(a)[1, 2, 3, 4]

但是在你給的代碼里得到的是生成器,這樣做的好處:

你不需要讀這個值兩次 你能得到許多孩子節點但是你不希望他們全部存入內存. 這種方法之所以能很好的運行是因為Python不關心方法的參數是不是一個列表.它只希望接受一個迭代器,所以不管是strings,lists,tuples或者generators都可以!這種方法叫做duck typing,這也是Python看起來特別cool的原因之一.但是這又是另外一個傳說了,另一個問題~~

好了,看到這里可以打住了,下面讓我們看看生成器的高級用法:

控制迭代器的窮盡

>>> class Bank(): # 讓我們建個銀行,生產許多ATM... crisis = False... def create_atm(self):... while not self.crisis:... yield "$100">>> hsbc = Bank() # 當一切就緒了你想要多少ATM就給你多少>>> corner_street_atm = hsbc.create_atm()>>> print(corner_street_atm.next())$100>>> print(corner_street_atm.next())$100>>> print([corner_street_atm.next() for cash in range(5)])['$100', '$100', '$100', '$100', '$100']>>> hsbc.crisis = True # cao,經濟危機來了沒有錢了!>>> print(corner_street_atm.next())<type 'exceptions.StopIteration'>>>> wall_street_atm = hsbc.create_atm() # 對于其他ATM,它還是True>>> print(wall_street_atm.next())<type 'exceptions.StopIteration'>>>> hsbc.crisis = False # 麻煩的是,盡管危機過去了,ATM還是空的>>> print(corner_street_atm.next())<type 'exceptions.StopIteration'>>>> brand_new_atm = hsbc.create_atm() # 只能重新新建一個bank了>>> for cash in brand_new_atm:... print cash$100$100$100$100$100$100$100$100$100...

它對于一些不斷變化的值很有用,像控制你資源的訪問.

Itertools,你的好基友

itertools模塊包含了一些特殊的函數可以操作可迭代對象.有沒有想過復制一個生成器?鏈接兩個生成器?把嵌套列表里的值組織成一個列表?Map/Zip還不用創建另一個列表?

來吧import itertools

來一個例子?讓我們看看4匹馬比賽有多少個排名結果:

>>> horses = [1, 2, 3, 4]>>> races = itertools.permutations(horses)>>> print(races)<itertools.permutations object at 0xb754f1dc>>>> print(list(itertools.permutations(horses)))[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]

理解迭代的內部機制

迭代是可迭代對象(對應iter()方法)和迭代器(對應next()方法)的一個過程.可迭代對象就是任何你可以迭代的對象(廢話啊).迭代器就是可以讓你迭代可迭代對象的對象(有點繞口,意思就是這個意思)


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成人黑人xx视频免费观看| 久久综合国产精品台湾中文娱乐网| 久久激情五月丁香伊人| 久久人人97超碰精品888| 欧美午夜美女看片| 日本精品中文字幕| 亚洲欧美精品中文字幕在线| 日韩欧美在线视频日韩欧美在线视频| 日韩欧美在线视频日韩欧美在线视频| 亚洲精品理论电影| 国产精品极品美女粉嫩高清在线| 久久亚洲精品成人| 亚洲美女av在线播放| 亚洲白虎美女被爆操| 国产精品一区二区三区在线播放| 欧美视频精品一区| 欧美高清videos高潮hd| 国自在线精品视频| 色综合久久88色综合天天看泰| 国产欧美精品日韩精品| 欧美尺度大的性做爰视频| 97香蕉久久超级碰碰高清版| 国产免费一区二区三区香蕉精| 91在线免费网站| 亚洲国产精品久久久久| 日韩国产精品亚洲а∨天堂免| 国产精品你懂得| 欧美极品在线播放| 国产精品青青在线观看爽香蕉| 国产视频在线一区二区| 91久久夜色精品国产网站| 精品国产乱码久久久久酒店| 日韩日本欧美亚洲| 日韩av不卡电影| 国产欧美精品一区二区三区-老狼| 青青久久av北条麻妃海外网| 亚洲欧美国产va在线影院| 国产亚洲成精品久久| 欧美一区三区三区高中清蜜桃| 九九九久久久久久| 亚洲欧美国产精品专区久久| 91精品免费视频| 国产福利精品av综合导导航| 久久精品久久久久久国产 免费| 国产精品视频最多的网站| 午夜精品一区二区三区在线| 成人在线国产精品| 蜜月aⅴ免费一区二区三区| 国内精品伊人久久| 2019中文字幕在线观看| 午夜免费久久久久| 久久人91精品久久久久久不卡| 欧美国产极速在线| 911国产网站尤物在线观看| 日本成熟性欧美| 日韩不卡在线观看| 国产日韩欧美电影在线观看| 久久理论片午夜琪琪电影网| 永久免费毛片在线播放不卡| 97在线视频精品| 欧美性少妇18aaaa视频| 久久777国产线看观看精品| 国模极品一区二区三区| 久久久久久com| 国产精品88a∨| 国产精品h片在线播放| 91极品视频在线| 欧美国产精品va在线观看| 在线观看日韩视频| 国产成人精品综合久久久| 午夜精品三级视频福利| 色一情一乱一区二区| 国产亚洲成精品久久| 日本成人黄色片| 欧美诱惑福利视频| 日韩免费观看在线观看| 亚洲视频在线观看网站| 欧美一区亚洲一区| 日韩精品视频在线观看网址| 久久在线免费观看视频| 久久偷看各类女兵18女厕嘘嘘| 日韩中文字幕视频在线观看| 欧美床上激情在线观看| 亚洲精品99999| 日韩欧美综合在线视频| 精品丝袜一区二区三区| 国产a∨精品一区二区三区不卡| 久久国产精品99国产精| 亚洲亚裔videos黑人hd| 精品偷拍各种wc美女嘘嘘| 欧美日韩国产丝袜美女| 午夜美女久久久久爽久久| 日韩精品福利在线| 亚洲国产小视频在线观看| 国产精品自拍小视频| 久久久久日韩精品久久久男男| 久久久久久久久久久av| 亚洲一区中文字幕| 欧美一区二区大胆人体摄影专业网站| 91精品国产一区| 日本一区二三区好的精华液| 日韩激情av在线免费观看| 国产午夜精品美女视频明星a级| 91丝袜美腿美女视频网站| 国产福利精品在线| 高清欧美性猛交| 国产在线精品播放| 精品无人区乱码1区2区3区在线| 中文字幕九色91在线| 日韩在线视频播放| 欧美日韩激情视频| 亚洲伊人久久综合| 精品视频一区在线视频| 精品无码久久久久久国产| 国产精品高清在线观看| 国产精品视频区1| 插插插亚洲综合网| 久久久久久久久国产精品| 九九精品视频在线观看| 欧美亚洲国产另类| 成人免费视频在线观看超级碰| 精品国产999| 亚洲国产高潮在线观看| www.亚洲成人| 久久伊人精品一区二区三区| 国产69精品久久久久99| 精品呦交小u女在线| 欧美性视频在线| 57pao精品| 欧美日本高清视频| 68精品国产免费久久久久久婷婷| 中文字幕九色91在线| 456亚洲影院| 国产美女久久精品香蕉69| 欧美黄网免费在线观看| 精品毛片三在线观看| 57pao国产精品一区| 亚洲成色777777女色窝| 国产欧美日韩免费看aⅴ视频| 中文字幕不卡在线视频极品| 91影院在线免费观看视频| 亚洲护士老师的毛茸茸最新章节| 成人免费淫片视频软件| 青青精品视频播放| 成人在线观看视频网站| 日韩欧中文字幕| 国产精品一区二区三区免费视频| 亚洲精品欧美日韩| 狠狠久久五月精品中文字幕| 色先锋资源久久综合5566| 亚洲精品电影网| 久久国产精品久久久| 国产精品wwwwww| 一区二区三区视频观看| 欧美午夜精品久久久久久浪潮| 91精品国产乱码久久久久久久久| 日韩成人中文字幕在线观看| 91精品久久久久久久久久另类| 日韩av高清不卡| 97人人模人人爽人人喊中文字| 在线免费观看羞羞视频一区二区| 国产精品高潮呻吟久久av黑人| 亚洲少妇中文在线| 国产午夜精品全部视频在线播放|