1. 程式人生 > >【python學習筆記】33:生成器、迭代器、高階函式

【python學習筆記】33:生成器、迭代器、高階函式

生成器

生成器(generator)相比列表推導式,只佔用很小的空間,因為它是一邊迴圈一邊推算,通過next()呼叫下一元素,並在結束時丟擲StopIteration異常,在語法上只要把[]換成()即可。

a = (i * i for i in range(10))
print(a)  # 生成器物件,不能直接輸出

# 用"next(生成器)"或者"生成器.__next__()"來返回下一個元素
print(a.__next__())  # 0
print(next(a))  # 1

for x in a:  # for本身也是在一個一個呼叫next()
    print(x, end=' '
) # 輸出剩下的4 9 16 25 36 49 64 81

可以在函式內使用yield關鍵字將該函式變成一個generator,每次呼叫next()時執行,執行到yield時候暫停下來並返回yield後跟的值,下次呼叫next()時繼續從剛剛暫停的yield語句的下一句繼續執行。

當某個next()呼叫沒有遇到yield就已經結束了整個函式時,就會丟擲StopIteration異常,而不需要raise StopIteration()

迭代器

可以依次訪問元素(即可以用for迴圈遍歷)的是可迭代物件(Iterable);可以用next()依次訪問的可迭代物件是迭代器(Iterator)。

生成器一定是迭代器,listdictstr是可迭代物件,但不是迭代器,可以iter()函式轉成迭代器。

from collections import Iterable, Iterator

a = [i for i in range(5)]  # 這是一個list
print(isinstance(a, Iterable))  # True,即可迭代
print(isinstance(a, Iterator))  # False,即不是迭代器

b = iter(a)  # 轉換為迭代器
print(b.__next__())  # 0
print(b.__next__())  # 1
for
n in b: print(n, end=' ') # 2 3 4

高階函式

函式可以傳給變數,也可以像普通變數一樣當做引數傳給函式,接受函式為引數的函式就是高階函式。

map()

高階函式map()接收一個函式,再接受一個Iterable,將函式作用在Iterable中的每個元素上,將返回值組成一個惰性Iterator序列並返回。

def fun(n):
    return n / 2


a = [i * i for i in range(5)]  # 可迭代物件(Iterable)
b = map(fun, a)  # 返回一個迭代器(Iterator)
print(list(b))  # [0.0, 0.5, 2.0, 4.5, 8.0]

reduce()

高階函式reduce()接收一個函式,再接受一個Iterable,將函式作用在Iterable中的前兩個元素上,將返回值與下一個元素一起再扔給該函式,如此反覆。

from functools import reduce


# 傳給reduce的函式要接收兩個引數
def fun(m, n):
    return m + n


a = [i * i for i in range(5)]  # 可迭代物件(Iterable)
b = reduce(fun, a)  # 反覆進行兩兩計算,最終返回計算結果
print(b)  # 30

filter()

高階函式filter()的輸入輸出形式和map()一樣,不過filter()是將傳入的函式作用到Iterable的每個元素上,最終只保留返回True的那些元素。也就是過濾掉一些元素,返回原Iterable的一個帶序子集。

from collections import Iterable, Iterator


def fun(n):
    if n < 2:
        return False
    if n < 4:
        return True
    i = 2
    while i * i <= n:
        if 0 == n % i:
            return False
        i += 1
    return True


a = range(50)  # Iterable
# print(isinstance(a, Iterator))  # False
b = filter(fun, a)  # 返回過濾後的Iterator
# print(isinstance(b, Iterator))  # True
print(list(b))  # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

sorted()

Java或者C++的排序可以指定一個比較器或者自定義比較大小的函式,在Python裡只是指定其key引數為某個函式,這個函式對排序的元素做一定的變換,使元素按照變換後的值來進行排序,但並未指定比較規則。

a = [3, -2, 8, -6, 0, 4, -9]
b = sorted(a, key=abs, reverse=True)  # 按絕對值從大到小排序
print(b)  # [-9, 8, -6, 4, 3, -2, 0]