python中的yield和return的區別

                           python中的yield和return的區別

return返回的是一個list列表,而yield每次調用只返回一個數值,毫無疑問,使用return空間開銷比較大,尤其是操作巨量數據的時候,操作一個大列表時間開銷也會得不償失
yield 生成器相比 return一次返回所有結果的優勢:

(1)反應更迅速

(2)更節省空間

(3)使用更靈活
yield和return的關係和區別:帶yield的函數是一個生成器,而不是一個函數了,這個生成器有一個函數就是next函數,next就相當於“下一步”生成哪個數,這一次的next開始的地方是接着上一次的next停止的地方執行的,所以調用next的時候,生成器並不會從foo函數的開始執行,只是接着上一步停止的地方開始,然後遇到yield後,return出要生成的數,此步就結束。
可以看出,yield 輸出的是一個對象,相當於是一個容器,想取什麼數據就取出什麼,而return 只會返回一個值,且return後面的代碼不會執行。

迭代器Iterables

迭代器就是你創建一個列表,你可以一個個的讀取。

lists,strings,files 等都是可以迭代的,只要你可以用for ... in ...,但是你必須把它們的值放到內存裏,當它們有很多值時就會消耗太多的內存.

lists = [1,2,3,4]
mys = [x*x for x in range(3)]
for i in mylist:
    print(i)

生成器generator

生成器也是迭代器,即迭代器包括生成器,但是你只能迭代他們一次,因爲他們不是全部在內存中,他們只有在調用的時候在內存中生成。

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

但是生成器是用()而不是用[]
還有你不能用for i in mygenerator第二次調用生成器
因爲其計算完就丟棄。

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)

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

一旦函數運行並沒有碰到yeild語句就認爲生成器已經爲空了.原因有可能是循環結束或者沒有滿足if/else之類的.
extend()是一個列表對象的方法,它可以把一個迭代對象添加進列表

生成器的好處

  • 你不需要讀這個值兩次
  • 你能得到許多孩子節點但是你不希望他們全部存入內存.
  • 這種方法之所以能很好的運行是因爲Python不關心方法的參數是不是一個列表.它只希望接受一個迭代器,所以不管是strings,lists,tuples或者generators都可以!
  • 這種方法叫做duck typing,

控制迭代器窮盡

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

迭代進階 itertools

設置起點和步長

itertools.count(start=0, step=1)

from itertools import *

for i in izip(count(1), ['a', 'b', 'c']):
    print i

(1, 'a')
(2, 'b')
(3, 'c')

itertools.cycle(iterable)

from itertools import *

i = 0
for item in cycle(['a', 'b', 'c']):
    i += 1
    if i == 10:
        break
    print (i, item)

(1, 'a')
(2, 'b')
(3, 'c')
(4, 'a')
(5, 'b')
(6, 'c')
(7, 'a')
(8, 'b')
(9, 'c')

itertools.repeat(object[, times])

from itertools import *

for i in repeat('over-and-over', 5):
    print i

over-and-over
over-and-over
over-and-over
over-and-over
over-and-over

itertools.chain(*iterables)
將多個迭代器作爲參數, 但只返回單個迭代器, 它產生所有參數迭代器的內容, 就好像他們是來自於一個單一的序列.

from itertools import *

for i in chain([1, 2, 3], ['a', 'b', 'c']):
    print i
1
2
3
a
b
c

itertools.groupby(iterable[, key])

from itertools import groupby
qs = [{'date' : 1},{'date' : 2}]
[(name, list(group)) for name, group in itertools.groupby(qs, lambda p:p['date'])]

Out[77]: [(1, [{'date': 1}]), (2, [{'date': 2}])]


>>> from itertools import *
>>> a = ['aa', 'ab', 'abc', 'bcd', 'abcde']
>>> for i, k in groupby(a, len):
...     print i, list(k)
...
2 ['aa', 'ab']
3 ['abc', 'bcd']
5 ['abcde']

itertools.permutations

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),
 ...

更多的見
(http://www.wklken.me/posts/2013/08/20/python-extra-itertools.html)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章