麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Python中關(guān)鍵字yield有什么作用?

2019-11-14 10:01:31
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

下面是調(diào)用它:

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

當(dāng)_get_child_candidates方法被調(diào)用的時(shí)候發(fā)生了什么?是返回一個(gè)列表?還是一個(gè)元祖?它還能第二次調(diào)用嗎?后面的調(diào)用什么時(shí)候結(jié)束?

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

Iterables

當(dāng)你創(chuàng)建了一個(gè)列表,你可以一個(gè)一個(gè)的讀取它的每一項(xiàng),這叫做iteration:

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

Mylist是可迭代的.當(dāng)你用列表推導(dǎo)式的時(shí)候,你就創(chuàng)建了一個(gè)列表,而這個(gè)列表也是可迭代的:

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

所有你可以用在for…in…語(yǔ)句中的都是可迭代的:比如lists,strings,files…因?yàn)檫@些可迭代的對(duì)象你可以隨意的讀取所以非常方便易用,但是你必須把它們的值放到內(nèi)存里,當(dāng)它們有很多值時(shí)就會(huì)消耗太多的內(nèi)存.

Generators

生成器也是迭代器的一種,但是你只能迭代它們一次.原因很簡(jiǎn)單,因?yàn)樗鼈儾皇侨看嬖趦?nèi)存里,它們只在要調(diào)用的時(shí)候在內(nèi)存里生成:

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

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

Yield

Yield的用法和關(guān)鍵字return差不多,下面的函數(shù)將會(huì)返回一個(gè)生成器:

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

在這里這個(gè)例子好像沒(méi)什么用,不過(guò)當(dāng)你的函數(shù)要返回一個(gè)非常大的集合并且你希望只讀一次的話,那么它就非常的方便了.

要理解Yield你必須先理解當(dāng)你調(diào)用函數(shù)的時(shí)候,函數(shù)里的代碼并沒(méi)有運(yùn)行.函數(shù)僅僅返回生成器對(duì)象,這就是它最微妙的地方:-)

然后呢,每當(dāng)for語(yǔ)句迭代生成器的時(shí)候你的代碼才會(huì)運(yùn)轉(zhuǎn).

現(xiàn)在,到了最難的部分:

當(dāng)for語(yǔ)句第一次調(diào)用函數(shù)里返回的生成器對(duì)象,函數(shù)里的代碼就開始運(yùn)作,直到碰到y(tǒng)ield,然后會(huì)返回本次循環(huán)的第一個(gè)返回值.所以下一次調(diào)用也將運(yùn)行一次循環(huán)然后返回下一個(gè)值,直到?jīng)]有值可以返回.

一旦函數(shù)運(yùn)行并沒(méi)有碰到y(tǒng)eild語(yǔ)句就認(rèn)為生成器已經(jīng)為空了.原因有可能是循環(huán)結(jié)束或者沒(méi)有滿足if/else之類的.

對(duì)于你的代碼的解釋

生成器:

# 這里你創(chuàng)建node方法的對(duì)象將會(huì)返回一個(gè)生成器def node._get_child_candidates(self, distance, min_dist, max_dist): # 這里的代碼你每次使用生成器對(duì)象的時(shí)候?qū)?huì)調(diào)用 if self._leftchild and distance - max_dist < self._median: yield self._leftchild if self._rightchild and distance + max_dist >= self._median: yield self._rightchild # 如果代碼運(yùn)行到這里,生成器就被認(rèn)為變成了空的調(diào)用:# 創(chuàng)建空列表和一個(gè)當(dāng)前對(duì)象索引的列表result, candidates = list(), [self]# 在candidates上進(jìn)行循環(huán)(在開始只保含一個(gè)元素)while candidates: # 獲得最后一個(gè)condidate然后從列表里刪除 node = candidates.pop() # 獲取obj和candidate的distance distance = node._get_dist(obj) # 如果distance何時(shí)將會(huì)填入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

這段代碼有幾個(gè)有意思的地方:

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

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

我們經(jīng)常這么用:

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

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

你不需要讀這個(gè)值兩次 你能得到許多孩子節(jié)點(diǎn)但是你不希望他們?nèi)看嫒雰?nèi)存. 這種方法之所以能很好的運(yùn)行是因?yàn)镻ython不關(guān)心方法的參數(shù)是不是一個(gè)列表.它只希望接受一個(gè)迭代器,所以不管是strings,lists,tuples或者generators都可以!這種方法叫做duck typing,這也是Python看起來(lái)特別cool的原因之一.但是這又是另外一個(gè)傳說(shuō)了,另一個(gè)問(wèn)題~~

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

控制迭代器的窮盡

>>> class Bank(): # 讓我們建個(gè)銀行,生產(chǎn)許多ATM... crisis = False... def create_atm(self):... while not self.crisis:... yield "$100">>> hsbc = Bank() # 當(dāng)一切就緒了你想要多少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,經(jīng)濟(jì)危機(jī)來(lái)了沒(méi)有錢了!>>> print(corner_street_atm.next())<type 'exceptions.StopIteration'>>>> wall_street_atm = hsbc.create_atm() # 對(duì)于其他ATM,它還是True>>> print(wall_street_atm.next())<type 'exceptions.StopIteration'>>>> hsbc.crisis = False # 麻煩的是,盡管危機(jī)過(guò)去了,ATM還是空的>>> print(corner_street_atm.next())<type 'exceptions.StopIteration'>>>> brand_new_atm = hsbc.create_atm() # 只能重新新建一個(gè)bank了>>> for cash in brand_new_atm:... print cash$100$100$100$100$100$100$100$100$100...

它對(duì)于一些不斷變化的值很有用,像控制你資源的訪問(wèn).

Itertools,你的好基友

itertools模塊包含了一些特殊的函數(shù)可以操作可迭代對(duì)象.有沒(méi)有想過(guò)復(fù)制一個(gè)生成器?鏈接兩個(gè)生成器?把嵌套列表里的值組織成一個(gè)列表?Map/Zip還不用創(chuàng)建另一個(gè)列表?

來(lái)吧import itertools

來(lái)一個(gè)例子?讓我們看看4匹馬比賽有多少個(gè)排名結(jié)果:

>>> 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)]

理解迭代的內(nèi)部機(jī)制

迭代是可迭代對(duì)象(對(duì)應(yīng)iter()方法)和迭代器(對(duì)應(yīng)next()方法)的一個(gè)過(guò)程.可迭代對(duì)象就是任何你可以迭代的對(duì)象(廢話啊).迭代器就是可以讓你迭代可迭代對(duì)象的對(duì)象(有點(diǎn)繞口,意思就是這個(gè)意思)


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 中文在线观看免费视频 | 日韩视频一区二区在线观看 | 精品三级内地国产在线观看 | 一本一道久久久a久久久精品91 | 一级全毛片 | 九九精品在线播放 | 丰满年轻岳中文字幕一区二区 | 久久精品九九 | 日本免费aaa观看 | 亚洲一级网站 | 欧美日韩在线播放 | 欧美成人三级视频 | 97中文字幕第一一一页 | 成人性生活视频 | av在线观| 国产精品啪 | 国产精品视频一区二区三区四区国 | 日韩精品网站在线观看 | japan护士性xxxⅹhd | 一区二区三区在线观看免费视频 | 久久一本日日摸夜夜添 | 99r国产精品 | 黄色片网页 | 99精品国产小情侣高潮露脸在线 | 一区二区三区欧美精品 | 成人福利在线观看 | 国产在线一级片 | 欧美精品一级片 | 激情小说另类 | 久久亚洲春色中文字幕久久 | 国产88久久久国产精品免费二区 | 黄色av片在线观看 | 国产精品久久久久久久亚洲按摩 | 成人免费福利视频 | 成年免费网站 | 午夜精品久久久久久久96蜜桃 | 黄色片网站在线播放 | 日日爱影院 | 中国av免费观看 | 日韩中文字幕一区二区三区 | 欧美一级高潮 |