Python——生成器、列表生成式、迭代器

Python列表生成式

列表推導式的一般語法

[express for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
....
for itemn in iterablen if conditionn
]

這種語法等價于以下代碼

s = []
for item1 in iterable1:
      if condition1:
          for item2 in iterable2:
              if condition2:
                ....
                for itemN in iterableN:
                    if conditionN:
                        expression

下面舉一些列表推導式的栗子:

a = [1,3,5,7,9,10]
b = ['a','b','c','d','e']

# a列表中所有項*2
c = [2*s for s in a]
print(c)
# 帶有條件的列表推導式
d = [s for s in a if s>=5]
print(d)

# 多item
e = [(x,y) for x in a for y in b if x > 0]
print(e)

  • Python中生成列表可以使用如下的表達式:
a = [x for x in range(10)]
# 0,1,2,3,4,5,6,7,8,9
  • 元組或列表賦值
t = ('128',222)
a,b = t
這里a,b將被賦值為t的兩個元素
等價于 a = t[0] b =t[1]
print(a)
print(b)
# 128 222

生成器

通過列表生成式,我們可以直接創建一個列表,但是受到內存的限制,列表的容量是有限的。而且我們創建的數據過于龐大會占用很大的內存空間。所以,如果列表元素可以按照某種算法推算出來,我們就可以在循環的過程中不斷推算后續的元素。這樣就不必創建列表。從而節省了大量的空間。在Python中,我們稱這種一邊循環一邊計算的機制,稱為生成器 generator,生成器用來創建Python序列的一個對象。它可以迭代龐大的序列,且不需要在內存中創建和存儲整個序列。任何使用yield的函數都稱為生成器

生成器的創建

通過列表生成式創建

要創建一個generator,我們可以把列表生成式的[]改成一個()這樣就創建了一個generator
生成器表達式是一個對象,它執行的計算與列表推導相同,但會迭代地生成結果。它的語法也與列表推導式相同,但要用圓括號代替方括號

  • 生成器表達式的語法
(expression for item1 in iterable1 if condition1 
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
)

生成器表達式和列表推導式不同,生成器表達式實際上不創建列表或者立即對圓括號內的表達式求值。相反,它會創建一個生成器對象,該對象通過迭代并按照需要生成的值,看個栗子

a = [1, 2, 3, 4]
b = (10 * i for i in a)
print(type(b))
print(b.__next__())
print(next(b))
>>>
<class 'generator'>
10
20

**使用生成器表達式和列表推導式可以極大地提高性能和n

L   = [x * x for x in range(10)]
L
g = (x*x for x in range(10))
g
# <generator object <genexpr> at 0x1022ef630>

這里L是一個list g是一個generator

使用yield

生成器本質上其實是一個函數,函數就會有返回值,我們在函數中使用yield

def gerator():
    print('ok')
    yield 1
    print('next')
    yield 2

g = gerator()
print(g)
print(next(g))
print(next(g))
######
<generator object gerator at 0x102210fc0>
ok
1
next
2

如果一個函數定義中包含yield關鍵字,那么這個函數就不再是一個普通函數,而是一個generator

generator和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最后一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句后返回。再次執行時從上次返回的yield語句處繼續執行

我們這樣定義函數后,直接執行這個函數不會被內部執行了,這個函數就會成為一個生成器對象
上面的生成器函數中,我們執行完第一個next中,程序會執行第一個yield的值,然后會記錄執行位置,再執行第二個next時從上一次記錄的位置繼續執行,執行中遇到return,會認為函數的結束,那么生成器也會結束。

讀取生成器的元素 next()

要生成的值并不在生成器中,而需要我們一個一個的去生成,可以通過next()函數獲得生成器generator()的下一個返回值:

>>> next(g)

generator保存的是算法,所以每次調用next(g),就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的錯誤
但是我們在使用generator后,基本上永遠不會調用next(),而是通過for循環來迭代,并且不需要關心stopIteration的錯誤.for循環要求作用的對象是迭代對象,生成器就是一個迭代對象。所以可以直接使用for循環來取生成器的值

for i in g:
    print(i)

會在內部調用生成器的next()方法

執行迭代器的函數 send(p)

生成器也是函數,可以使用send(p)執行生成器函數并傳遞一個函數,這個函數會傳遞到yield的對象中。

  • 第一次使用send進入函數時只能傳遞一個None值,也就是說第一次send前如果沒有next只能發送None數據

b.send(None)

def bar():
    print('before yield')
    count = yield 123
    print(count)
    yield 234
b = bar()

b.send(None)
b.send('abc')

Python 迭代器

在Python中,可以直接作用于for循環的數據類型可以分為:
1.集合數據類型 list、tuple、dict、set、str等
2.生成器generator 包括生成器和帶yield的生成器函數
這些可以作用于for循環的對象統稱為可迭代對象:Iterable
在Python中可以使用isinstance()判斷一個對象是否是Iterable對象

from collections import Iterable

print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance((), Iterable))
print(isinstance('123', Iterable))
print(isinstance(100,Iterable))
#True
True
True
True
False
  • 判斷是否是迭代器
    我們可以使用isinstance()判斷一個對象是否是迭代器Iterator對象
from collections import Iterator

print(isinstance([], Iterator))
print(isinstance((), Iterator))
print(isinstance({}, Iterator))
print(isinstance('1111',Iterator))

我們可以看出list dict str tuple等數據類型雖然是Iterable,卻不是Iterator,So
迭代器一定是可迭代對象,可迭代對象不一定是迭代器
那么為什么Python中 list dict str等數據類型不是Iterator?

因為Python中的Iterator對象表示的是一個數據流,而Iterator對象可以被next()函數調用并不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。這個數據流可以看做是一個有序序列。但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的的計算是惰性的,只有在需要返回下一給數據時才會計算
而Iterator可以表示一個無限大的數據流。
迭代器滿足的條件:
1有iter方法
2有next方法

  • 可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator
  • 對于for循環,在內部所完成的三件事:
    1 調用可迭代對象的iter方法返回一個迭代器對象
    2 不斷調用迭代器對象的next方法
    3 捕獲StopIterator異常
for循環內部圖解
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容