What does the 「yield」 keyword do?

微信公衆號:stackflow
若有問題或建議,請公衆號留言
Question:https://stackoverflow.com/questions/1132941/
最近更新:2018-12-17node

需求分析

英文yield,意爲屈從、量產、投資收益。而python中則是一個表達式,面試中常常會被問到。那yield是用來幹嗎的呢?首先咱們要了解的是:iterable(迭代)、generator(生成器),而後纔是yield(生成可迭代對象)python

 1def _get_child_candidates(self, distance, min_dist, max_dist):
2    if self._leftchild and distance - max_dist < self._median:
3        yield self._leftchild
4    if self._rightchild and distance + max_dist >= self._median:
5        yield self._rightchild
6
7# the caller
8result, candidates = [], [self]
9while candidates:
10    node = candidates.pop()
11    distance = node._get_dist(obj)
12    if distance <= max_dist and distance >= min_dist:
13        result.extend(node._values)
14    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
15return result
複製代碼

Answers

Iterables

全部可用for…in…來遍歷的對象都是可迭代的,如lists, strings, files…面試

1>>> mylist = [x*x for x in range(3)]
2>>> for i in mylist:
3...    print(i)
40
51
64
複製代碼

Generators

生成器都是可迭代的,只是只能迭代一次。由於生成器不存儲全部值到內存中,而是動態的生成值。 微信

 1mygenerator = (x*x for x in range(3))
2for i in mygenerator:
3    print(i)
4
5print(mygenerator)
6for i in mygenerator: # 無輸出
7    print(i)
8
9# the result:
100
111
124
13<generator object <genexpr> at 0x000002AB4F68B258>
複製代碼

yield

用法同return,只是函數返回一個可迭代的生成器app

 1>>> def createGenerator():
2...    mylist = range(3)
3...    for i in mylist:
4...        yield i*i
5...
6>>> mygenerator = createGenerator() # create a generator
7>>> print(mygenerator) # mygenerator is an object!
8<generator object createGenerator at 0xb7555c34>
9>>> for i in mygenerator:
10...     print(i)
110
121
134
複製代碼

以上只是基礎,問題中的代碼執行過程更複雜,分析以下:
一、while循環遍歷列表,每次被迭代時,列表會擴展
二、extend方法是追加值到列表中
Python指望迭代,所以它能夠處理字符串、列表、元組和生成器!這就是Python如此cool的緣由之一。函數

下面嘗試一下生成器的高級用法:post

Controlling a generator exhaustion

 1>>> class Bank(): # Let's create a bank, building ATMs
2...    crisis = False
3...    def create_atm(self):
4...        while not self.crisis:
5...            yield "$100"
6>>> hsbc = Bank() # When everything's ok the ATM gives you as much as you want
7>>> corner_street_atm = hsbc.create_atm()
8>>> print(corner_street_atm.next())
9$100
10>>> print(corner_street_atm.next())
11$100
12>>> print([corner_street_atm.next() for cash in range(5)])
13['$100''$100''$100''$100''$100']
14>>> hsbc.crisis = True # Crisis is coming, no more money!
15>>> print(corner_street_atm.next())
16<type 'exceptions.StopIteration'>
17>>> wall_street_atm = hsbc.create_atm() # It's even true for new ATMs
18>>> print(wall_street_atm.next())
19<type 'exceptions.StopIteration'>
20>>> hsbc.crisis = False # The trouble is, even post-crisis the ATM remains empty
21>>> print(corner_street_atm.next())
22<type 'exceptions.StopIteration'>
23>>> brand_new_atm = hsbc.create_atm() # Build a new one to get back in business
24>>> for cash in brand_new_atm:
25...    print cash
26$100
27$100
28$100
29$100
30$100
31$100
32$100
33$100
34$100
35...
複製代碼

Itertools, your best friend

itertools包含了用於操做迭代的特殊函數,好比複製、鏈接ui

 1>>> horses = [1234]
2>>> races = itertools.permutations(horses)
3>>> print(races)
4<itertools.permutations object at 0xb754f1dc>
5>>> print(list(itertools.permutations(horses)))
6[(1234),
7 (1243),
8 (1324),
9 (1342),
10 (1423),
11 (1432),
12 (2134),
13 (2143),
14 (2314),
15 (2341),
16 (2413),
17 (2431),
18 (3124),
19 (3142),
20 (3214),
21 (3241),
22 (3412),
23 (3421),
24 (4123),
25 (4132),
26 (4213),
27 (4231),
28 (4312),
29 (4321)]
複製代碼

迭代是實現可迭代(iter()方法)和迭代器(next()方法)的過程。迭代器是容許您在迭代器上迭代的對象。有點繞,實操一下吧。^-^spa

相關文章
相關標籤/搜索