1. 程式人生 > 其它 >Python迭代器生成器與生成式

Python迭代器生成器與生成式

技術標籤:python

Python迭代器生成器與生成式

什麼是迭代

迭代是重複反饋過程的活動,其目的通常是為了逼近所需目標或結果。每一次對過程的重複稱為一次“迭代”,而每一次迭代得到的結果會作為下一次迭代的初始值。

例如for迴圈

a = ['abc', 123, ['4', 45]]
for i in a:
    print(i)
#==========輸出=============
abc
123
['4', 45]

for就是把這個列表迭代了一遍,但是根據迭代的定義每一次迭代得到的結果會作為下一次迭代的初始值。這也沒看到用了上一次的值啊。

這裡介紹兩個函式__iter__()

__next__,一個可迭代序列(同時它也是一個物件),它有一個__iter__()方法,可以返回一個迭代器物件,這個迭代器物件裡面有一個__next__()方法,它可以將迭代器物件一個一個向下迭代。

例如上例

a = ['abc', 123, ['4', 45]]

#print(a.__iter__())
x = a.__iter__()
print(x.__next__())
print(x.__next__())
print(x.__next__())

##其實還有一種迭代形式,一個呼叫內建方法一個呼叫外部方法罷了
x = iter()
next(x)
next(x)
next(x)
x = iter(a) print(next(x)) print(next(x)) print(next(x)) #===========輸出結果========= abc 123 ['4', 45] abc 123 ['4', 45]

但是如果再加一個print(x.__next__())的話python會丟擲一個異常。

然後我們可以結合while迴圈就可以大致猜出for迭代時的內部執行機理了。

a = ['abc', 123, ['4', 45]]

y = a.__iter__()
while True:
    try:
        print(y.__next__())
    except
StopIteration: break #===========輸出================ abc 123 ['4', 45]

這樣就把列表a迭代完了。

什麼是生成式

要建立一個列表,就要有一箇中括號,裡面的資料就是列表的內容。如果我要建立一個列表,列表裡面有按順序的1~100所有的整數,一個一個輸入嗎?

有人可能說用迴圈,例如

x = []
for i in range(1, 101):
    x.append(i)

確實這樣是可以的,但是有了生成式可能會更加簡單一點

x = [i for i in range(1, 101)]

再中括號裡面,一個應該寫入資料的地方放一個迴圈,在C語言看來這簡直就是瘋了。不過這也體現了python的靈活強大。

其實中括號裡面除了加for迴圈還能加條件判斷,例如

x = [i for i in range(1, 101) if i % 2 and not i % 3]
#列舉出所有1~100能被3整除不能被2整除的數

除了list列表有這種操作以外,還有字典可以這樣操作

字典

dict1 = {i:i + 1 for i in range(1, 101)if i % 2 and not i % 3 }

執行結果

{3: 4, 9: 10, 15: 16, 21: 22, 27: 28, 33: 34, 39: 40, 45: 46, 51: 52, 57: 58, 63: 64, 69: 70, 75: 76, 81: 82, 87: 88, 93: 94, 99: 100}

應該能看出點什麼來了,也挺簡單。

什麼是生成器

就是有一個跟return差不多的東西yieldreturn返回之後程式就退出了,但是yield會把程式暫停,然後等你需要的時候來繼續執行,但是跟return又有一點不一樣,yield是迭代器的一種,返回的是一個生成器物件,需要借用next()函式來進行迭代。

其實yield就是一種特殊的迭代器。

def sc1():
    yield 'one'
    yield 'two'

def sc2():
    return 'one'


s1 = sc1()
s2 = sc2()
print(type(s1))
print(type(next(s1)))
print(type(s2))

輸出

<class 'generator'>
<class 'str'>
<class 'str'>

對於生成器的使用,最簡單的例如

def sc():
    print('進入函式1')
    yield 'one'
    print('進入函式2')
    yield 'two'

s = sc()
print(next(s))
print(next(s))

#============輸出===========
進入函式1
one
進入函式2
two

使用與迭代器幾乎一模一樣

用這個生成一個斐波拉契數列可以這樣寫

def feb(x):
    count = 0
    a = 0
    b = 1
    while count < x:
        yield a
        a, b = b, a + b
        count += 1

這樣就會生成一個斐波拉契數列前x項的可迭代序列

可以測試一下,用for迴圈迭代它

for i in feb(10):
    print(i,end=' ')

輸出

0 1 1 2 3 5 8 13 21 34