列表特性:列表是一次性生成的
a = [1,2,3,4,5,6,7,8,9]
或
[ i*2 for i in range(10)] ###--->列表生成式
===[2,4,6,8,10,12,14,16,18,20]===
兩個列表的區別:
1列表是寫死的,2列表可以裏面做一些操作把相應的東西輸出出來
列表生成式目的是爲了使代碼更簡潔,且可以實現更復雜的功能,如將i的值傳至函數中
[fun(i) for i in range(10)]
生成式:通過生成式可以直接創建一個列表,但受內存大小的限制,列表的容量是有限的,而且創建一個大數據量的列表,不僅佔用的內存空間很大,而且如果僅訪問前面幾個元素,那麼後面的元素所佔用的空間都浪費掉了。
所以,如果列表可以按照某種算法推算出來,我們可以在循環的過程中推斷出後續需要的列表元素而不需要創建完整的列表,從而大大節省了內存空間。在python中這種一邊循環了邊推算下一個列表元素的方式稱之爲生成器:generator
創建一個generator有很多方法,第一種簡單的方法爲把列表生成式的[]修改爲(),就創建了一個generator
[ i*2 for i in range(10)] ###--->列表生成式
==結果===[2,4,6,8,10,12,14,16,18,20]===
( i*2 for i in range(10)) ###--->generator
==結果===<generator object <genexpr> at 0x1022ef630>===
generator是每調用一次則生成一個元素,若沒調用則不生成後面的元素,從而節省內存空間
例:
g = ( i*2 for i in range(10))
print(g.__next__())
print(g.__next__())
print('********')
print(g.__next__())
==結果===
0
2
********
4
它只有__next__()方法,沒有其他方法,它不能被切片,如想取第3個值g(2)是不行的
以上方式也可以用循環的方式去調用它
如斐波那契數列,除第一個數外,任意一個數都是由前面兩個數相加得到:
1,1,2,3,5,8,13,21,34.......
斐波那契數列用列表生成式寫不出來,但是用函數卻很容易:
def fib(max):
n,a,b=0,0,1
while n < max:
print(b)
a,b= b,a+b
n = n+1
return 'done'
fib(100)
注意:
a,b= b,a+b
並非是
a = b
b = a+b
這麼簡單的事情
它應該是
t (b,a+b)
a = t[0]
b = t[1]
但不必顯示地寫出t變量就可進行賦值
而如果需要把上面的這個函數變成一個生成器,那麼只需要修改一個代碼
def fib(max):
n,a,b=0,0,1
while n < max:
yield b
a,b= b,a+b
n = n+1
return 'done'
print(fib(100))
==結果===<generator object fib at 0x1022ef630>===
那需要需要輸出裏面的內容呢!操作如下
f = fib(100)
print(f.__next__())
print(f.__next__())
那如果前面有幾個next的時候,再用for去循環它的時候,那麼它是從中間開始輸出生成的
假如next的數量超出生成器的範圍的時候,會拋出StopIteration異常,就需要異常捕捉,如上面的函數
def fib(max):
n,a,b=0,0,1
while n < max:
yield b #函數中斷的位置,調用next時返回這個位置
a,b= b,a+b
n = n+1
return 'done'
g = fib(10)
while True:
try:
x = next(g) #內置方法,與__next
print('g:',x)
except StopIteration as e:
print('Generator return value:',e.value)
break