你可使用 Lambda 表達式建立匿名函數,即沒有名稱的函數。lambda 表達式很是適合快速建立在代碼中之後不會用到的函數。尤爲對高階函數或將其餘函數做爲參數的函數來講,很是實用。python
咱們可使用 lambda 表達式將如下函數less
def multiply(x, y): return x * y
簡寫爲:函數
double = lambda x, y: x * y
測試
lambda
表示這是一個 lambda 表達式。lambda
以後是該匿名函數的一個或多個參數(用英文逗號分隔),而後是一個英文冒號 :
。和函數類似,lambda 表達式中的參數名稱是隨意的。map()
是一個高階內置函數,接受函數和可迭代對象做爲輸入,並返回一個將該函數應用到可迭代對象的每一個元素的迭代器。下面的代碼使用 map()
計算 numbers
中每一個列表的均值,並建立列表 averages
。測試運行這段代碼,看看結果如何。spa
經過將 mean
函數替換爲在 map()
的調用中定義的 lambda 表達式,重寫這段代碼,使代碼更簡練。code
numbers = [ [34, 63, 88, 71, 29], [90, 78, 51, 27, 45], [63, 37, 85, 46, 22], [51, 22, 34, 11, 18] ] def mean(num_list): return sum(num_list) / len(num_list) averages = list(map(mean, numbers)) print(averages)
我這麼改:orm
mean = lambda num_list: sum(num_list) / len(num_list) averages = list(map(mean, numbers))
但其實能夠直接將lambda整個寫到map參數中averages = list(map(lambda x: sum(x) / len(x), numbers))
對象
filter()
是一個高階內置函數,接受函數和可迭代對象做爲輸入,並返回一個由可迭代對象中的特定元素(該函數針對該元素會返回 True)組成的迭代器。下面的代碼使用 filter()
從 cities
中獲取長度少於 10 個字符的名稱以建立列表 short_cities
。測試運行這段代碼,看看結果如何。ip
經過將 is_short
函數替換爲在 filter()
的調用中定義的 lambda 表達式,重寫這段代碼,使代碼更簡練。內存
cities = ["New York City", "Los Angeles", "Chicago", "Mountain View", "Denver", "Boston"] def is_short(name): return len(name) < 10 short_cities = list(filter(is_short, cities)) print(short_cities)
改成 short_cities = list(filter(lambda x: len(x) < 10, cities))
迭代器是每次能夠返回一個對象元素的對象,例如返回一個列表。咱們到目前爲止使用的不少內置函數(例如 enumerate)都會返回一個迭代器。
迭代器是一種表示數據流的對象。這與列表不一樣,列表是可迭代對象,但不是迭代器,由於它不是數據流。
生成器是使用函數建立迭代器的簡單方式。也可使用類定義迭代器,更多詳情請參閱此處。
下面是一個叫作 my_range
的生成器函數,它會生成一個從 0 到 (x - 1) 的數字流。
def my_range(x): i = 0 while i < x: yield i i += 1
注意,該函數使用了 yield
而不是關鍵字 return。這樣使函數可以一次返回一個值,而且每次被調用時都從停下的位置繼續。關鍵字 yield 是將生成器與普通函數區分開來的依據。
請本身寫一個效果和內置函數 enumerate
同樣的生成器函數。
以下所示地調用該函數:
lessons = ["Why Python Programming", "Data Types and Operators", "Control Flow", "Functions", "Scripting"] for i, lesson in my_enumerate(lessons, 1): print("Lesson {}: {}".format(i, lesson))
應該會輸出:
Lesson 1: Why Python Programming Lesson 2: Data Types and Operators Lesson 3: Control Flow Lesson 4: Functions Lesson 5: Scripting
my_enumerate
函數實現:
def my_enumerate(iterable, start=0): """ return enumerate iterable """ for x in zip(range(start, len(iterable)+start), iterable): yield x
若是可迭代對象太大,沒法完整地存儲在內存中(例如處理大型文件時),每次可以使用一部分頗有用。
實現一個生成器函數 chunker
,接受一個可迭代對象並每次生成指定大小的部分數據。
以下所示地調用該函數:
for chunk in chunker(range(25), 4): print(list(chunk))
應該會輸出:
[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]
chunker
函數實現以下:
def chunker(iterable, size): """Yield successive chunks from iterable of length size.""" for i in range(0, len(iterable), size): yield iterable[i:i + size]
可迭代的range()
很強大,能夠用len()
也能夠用切片。
你可能會疑問,爲什麼要使用生成器,而不使用列表。下面這段摘自 stack overflow 頁面 的內容回答了這個問題:
生成器是構建迭代器的 「懶惰」 方式。當內存不夠存儲完整實現的列表時,或者計算每一個列表元素的代價很高,你但願儘可能推遲計算時,就可使用生成器。可是這些元素只能遍歷一次。
另外一種詳細的解釋以下(詳細說明參見 該 stack overflow 頁面。)
因爲使用生成器是一次處理一個數據,在內存和存儲的需求上會比使用list方式直接所有生成再存儲節省不少資源。
由此區別,在處理大量數據時,常用生成器初步處理數據後,再進行長期存儲,而不是使用 list。由於不管使用生成器仍是 list,都是使用過就要丟棄的臨時數據。既然功能和結果同樣,那就不如用生成器。
可是生成器也有本身的侷限,它產生的數據不能回溯,不像list能夠任意選擇。