現(xiàn)在有個需求,看列表[0, 1, 2, 3, 4, 5],要求你把列表里的每個值加1,你怎么實現(xiàn)?
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:域名申請、虛擬空間、營銷軟件、網(wǎng)站建設、寶坻網(wǎng)站維護、網(wǎng)站推廣。
可以使用for循環(huán),while循環(huán)
map方式
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a = map(lambda x:x+1, a)
>>> a
<map object at 0x101d2c630>
>>> for i in a:print(i)
...
3
5
7
9
11
高級方式:
列表生成式方式
>>> a = [i+1 for i in range(10)]
>>> a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>
通過列表生成式,我們可以直接創(chuàng)建一個列表。但是,收到內存限制,列表容量是有限的。而且,創(chuàng)建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅使用其中的幾個元素,那后面的元素所占用的空間就浪費掉了。
所以,如果列表中的元素可以按照某種算法推算出來,那是否可以在循環(huán)的過程中推算出后續(xù)的元素呢?就不需要創(chuàng)建完整的list,從而節(jié)省大量的空間。在Python中,一邊循環(huán)一邊計算的機制,稱為生成器:generator.
要創(chuàng)建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創(chuàng)建了一個generator
生成器的特性:
1.預先定義一個生產(chǎn)輸?shù)姆秶褂靡粋€生產(chǎn)一個,不占用內存空間
2.只能往下不斷取數(shù),不能回退
3.走到最后,報stopIteration錯誤
##這里生成大量的數(shù)據(jù),需要一段時間
>>> a = [i for i in range(100000000000000)]
##列表生成式,立刻生成,因為是調用net()方法時才產(chǎn)生數(shù)據(jù),調用一次產(chǎn)生一次
>>> a = (i for i in range(100000000000000))
>>>
>>>
>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> g = (i*2 for i in range(10))
>>> g
<generator object <genexpr> at 0x00000237FF9BF2B0>
通過next()函數(shù)獲得generator的下一個返回值
>>> next(g)
0
>>> next(g)
2
>>> next(g)
4
>>>
>>> next(g)
16
>>> next(g)
18
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
#可使用for循環(huán)調用
#創(chuàng)建了一個generator后,基本上永遠不會調用next(),而是通過for循環(huán)來迭代它,并且不需要關心StopIteration的錯誤
>>> g = (i*2 for i in range(10))
>>> for n in g:
... print(n)
...
0
2
4
6
8
10
12
14
16
18
>>>
generator非常強大。如果推算的算法比較復雜,用類似列表生成式的for循環(huán)無法實現(xiàn)的時候,可以使用函數(shù)來實現(xiàn)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
# 相當于t = a+b, a = b,b = t,但不需要顯式寫出臨時變量t就可以賦值
a, b = b, a + b
n = n + 1
return 'done'
fib(10)
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
1
1
2
3
5
8
13
21
34
55
Process finished with exit code 0
仔細觀察。fib函數(shù)實際上已經(jīng)定義了斐波那契數(shù)列的推算規(guī)則,可以從第一個元素開始推算出后續(xù)的任意元素,這種邏輯其實已經(jīng)很類似generator,實際只需要把print(b)改為yield b就變成了生成器。
如果一個函數(shù)定義中包含yield關鍵字,那么這個函數(shù)就不再是一個普通函數(shù),而是一個generator.
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
# 用for循環(huán)輸出內容
for i in fib(10):
print(i)
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
1
1
2
3
5
8
13
21
34
55
Process finished with exit code 0
print(fib(10))
<generator object fib at 0x000002BF85F8B888>
普通函數(shù)是順序執(zhí)行的,遇到return語句或最后一行函數(shù)語句就返回數(shù)據(jù),并凍結當前的執(zhí)行過程
generator的執(zhí)行流程是每次調用next()的時候執(zhí)行,遇到y(tǒng)eild語句返回,再次調用next()時從上次yeild語句處繼續(xù)執(zhí)行。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
data = fib(10)
print(data.__next__())
print(data.__next__())
print("做別的事情")
print(data.__next__())
print(data.__next__())
print(data.__next__())
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
1
1
做別的事情
2
3
5
Process finished with exit code 0
用for循環(huán)調用generator時,發(fā)現(xiàn)拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
g = fib(10)
while True:
try:
x = next(g)
print('g:', x)
except StopIteration as e:
print('Generator return value:', e.value)
break
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
g: 13
g: 21
g: 34
g: 55
Generator return value: done
Process finished with exit code 0
send作用
1.喚醒并繼續(xù)執(zhí)行
2.發(fā)送一個信息到生成器內部
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
def fib(max):
n,a,b = 0,0,1
while n < max:
#print(b)
sign=yield b
a,b = b,a+b
if sign=="stop":
print(sign)
n += 1
return 'done'
f = fib(6)
print(next(f))
print(next(f))
print(next(f))
f.send("stop")
print(next(f))
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
1
1
2
stop
5
python3中
range()就是創(chuàng)建了一個生成器,用到的時候才會生成數(shù)據(jù)
Python2中
range()是創(chuàng)建一個定義大小的列表,
xrange()是創(chuàng)建了一個一個生成器,和Python3中的range()相同
>python3
Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> range(100000000000000000000)
range(0, 100000000000000000000)
>>> type(range(10))
<class 'range'>
>>> quit()
>python2
Python 2.7.16 (v2.7.16:413a49145e, Mar 4 2019, 01:37:19) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> xrange(100000000)
xrange(100000000)
>>> range(10000000)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37...]
>>> type(range(10))
<type 'list'>
>>> type(xrange(10))
<type 'xrange'>
我們已經(jīng)知道,可以用于for循環(huán)的數(shù)據(jù)類型有以下幾種:
一類是集合數(shù)據(jù)類型,如list,tuple,dict,set,str等;
一類是generator,包括生成器和帶yeild的generator function。
這些可以直接作用于for循環(huán)的對象稱為可迭代對象(Iterable)
可以使用isinstance()判斷一個對象是否是Iterable對象
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
生成器不但可以用for循環(huán),還可以被next()函數(shù)不斷調用并返回下一個值,直到最后拋出StopIteration錯誤表示無法繼續(xù)返回下一個值。
可以被next()函數(shù)調用并不斷返回下一個值的對象稱為迭代器(Iterator)
可以使用isinstance()判斷一個對象是否是Iterator對象
python3
>>> from collections import Iterator
>>> isinstance(range(10),Iterator)
False
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是迭代器,但list,tuple,set,dict,str雖然是可迭代對象,但不是迭代器。
可以使用iter()函數(shù)把list,str,dict,set變?yōu)榈?/p>
>>> isinstance(iter([]),Iterator)
True
>>> isinstance(iter(""),Iterator)
True
>>> isinstance(iter({}),Iterator)
True
>>>
為什么list,set,dict,str不是迭代器?
因為Python的迭代器對象表示的是一個數(shù)據(jù)流,Iterator對象可以被next()函數(shù)調用并不斷返回下一個數(shù)據(jù),直到?jīng)]有數(shù)據(jù)時拋出StopIteration錯誤。可以把這個數(shù)據(jù)流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數(shù)實現(xiàn)按需計算下一個數(shù)據(jù),所以Iterator的計算是惰性的,只有在需要返回下一個數(shù)據(jù)時才會計算。
Iterator甚至可以表示一個無限大的數(shù)據(jù)流,例如全體自然數(shù)。而使用list是永遠不可能存儲全體自然數(shù)的。
1.凡是可作用于for循環(huán)的對象都是Iterable類型;
2.凡是可作用于next()函數(shù)的對象都是Iterator類型,它們表示一個惰性計算的序列;
3.集合數(shù)據(jù)類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個Iterator對象。
4.Python3的for循環(huán)本質上就是通過不斷調用next()函數(shù)實現(xiàn)的,例如:
for x in [1, 2, 3, 4, 5]:
pass
實際上完全等價于:
# 首先獲得Iterator對象:
it = iter([1, 2, 3, 4, 5])
# 循環(huán):
while True:
try:
# 獲得下一個值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循環(huán)
break
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
網(wǎng)站名稱:生成器和迭代器-創(chuàng)新互聯(lián)
網(wǎng)頁URL:http://vcdvsql.cn/article18/ddgjdp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供云服務器、域名注冊、網(wǎng)站導航、手機網(wǎng)站建設、網(wǎng)站改版、面包屑導航
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)