[零基礎學python]大話題小函數(1)

開篇就要提到一個大的話題:編程範型。什麼是編程範型?引用維基百科中的解釋python

編程範型或編程範式(英語:Programming paradigm),(範即模範之意,範式即模式、方法),是一類典型的編程風格,是指從事軟件工程的一類典型的風格(能夠對照方法學)。如:函數式編程、程序編程、面向對象編程、指令式編程等等爲不一樣的編程範型。程序員

編程範型提供了(同時決定了)程序員對程序執行的見解。例如,在面向對象編程中,程序員認爲程序是一系列相互做用的對象,而在函數式編程中一個程序會被看做是一個無狀態的函數計算的串行。express

正如軟件工程中不一樣的羣體會提倡不一樣的「方法學」同樣,不一樣的編程語言也會提倡不一樣的「編程範型」。一些語言是專門爲某個特定的範型設計的(如Smalltalk和Java支持面向對象編程,而Haskell和Scheme則支持函數式編程),同時還有另外一些語言支持多種範型(如Ruby、Common Lisp、Python和Oz)。編程

編程範型和編程語言之間的關係可能十分複雜,因爲一個編程語言能夠支持多種範型。例如,C++設計時,支持過程化編程、面向對象編程以及泛型編程。然而,設計師和程序員們要考慮如何使用這些範型元素來構建一個程序。一我的能夠用C++寫出一個徹底過程化的程序,另外一我的也能夠用C++寫出一個純粹的面向對象程序,甚至還有人能夠寫出雜揉了兩種範型的程序。網絡

無論看官是初學者仍是老油條,都建議將上面這段話認真讀完,無論理解仍是不理解,總能有點感受的。app

這裏推薦一篇文章,這篇文章來自網絡:《主要的編程範型》編程語言

扯了很多編程範型,今天本講要講什麼呢?今天要介紹幾個python中的小函數,這幾個函數都是從函數式編程借鑑過來的,它們就是:ide

filter、map、reduce、lambda、yield函數式編程

有了它們,最大的好處是程序更簡潔;沒有它們,程序也能夠用別的方式實現,只不過麻煩一些罷了。因此,仍是能用則用之吧。函數

lambda

lambda函數,是一個只用一行就能解決問題的函數,聽着是多麼誘人呀。看下面的例子:

>>> def add(x):     #定義一個函數,將輸入的變量增長3,而後返回增長以後的值
...     x +=3
...     return x
... 
>>> numbers = range(10)
>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  #有這樣一個list,想讓每一個數字增長3,而後輸出到一個新的list中

>>> new_numbers = []
>>> for i in numbers:
...     new_numbers.append(add(i))  #調用add()函數,並append到list中
... 
>>> new_numbers
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

在這個例子中,add()只是一箇中間操做。固然,上面的例子徹底能夠用別的方式實現。好比:

>>> new_numbers = [ i+3 for i in numbers ]
>>> new_numbers
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

首先說明,這種列表解析的方式是很是很是好的。

可是,咱們恰恰要用lambda這個函數替代add(x),若是看官和我同樣這麼偏執,就能夠:

>>> lam = lambda x:x+3
>>> n2 = []
>>> for i in numbers:
...     n2.append(lam(i))
... 
>>> n2
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

這裏的lam就至關於add(x),請看官對應一下,這一行lambda x:x+3就完成add(x)的三行(仍是兩行?),特別是最後返回值。還能夠寫這樣的例子:

>>> g = lambda x,y:x+y  #x+y,並返回結果
>>> g(3,4)
7
>>> (lambda x:x**2)(4)  #返回4的平方
16

經過上面例子,總結一下lambda函數的使用方法:

  • 在lambda後面直接跟變量
  • 變量後面是冒號
  • 冒號後面是表達式,表達式計算結果就是本函數的返回值

爲了簡明扼要,用一個式子表示是必要的:

lambda arg1, arg2, ...argN : expression using arguments

要特別提醒看官:雖然lambda 函數能夠接收任意多個參數 (包括可選參數) 而且返回單個表達式的值,可是lambda 函數不能包含命令,包含的表達式不能超過一個。不要試圖向 lambda 函數中塞入太多的東西;若是你須要更復雜的東西,應該定義一個普通函數,而後想讓它多長就多長。

就lambda而言,它並無給程序帶來性能上的提高,它帶來的是代碼的簡潔。好比,要打印一個list,裏面依次是某個數字的1次方,二次方,三次方,四次方。用lambda能夠這樣作:

>>> lamb = [ lambda x:x,lambda x:x**2,lambda x:x**3,lambda x:x**4 ]
>>> for i in lamb:
...     print i(3),
... 
3 9 27 81

lambda作爲一個單行的函數,在編程實踐中,能夠選擇使用。根據個人經驗,儘可能少用,由於它或許更多地是爲減小單行函數的定義而存在的。

map

先看一個例子,仍是上面講述lambda的時候第一個例子,用map也可以實現:

>>> numbers
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      #把列表中每一項都加3

>>> map(add,numbers)                #add(x)是上面講述的那個函數,可是這裏只引用函數名稱便可
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

>>> map(lambda x: x+3,numbers)      #用lambda固然能夠啦
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

map()是python的一個內置函數,它的基本樣式是:map(func, seq),func是一個函數,seq是一個序列對象。在執行的時候,序列對象中的每一個元素,按照從左到右的順序,依次被取出來,並塞入到func那個函數裏面,並將func的返回值依次存到一個list中。

在應用中,map的所能實現的,也能夠用別的方式實現。好比:

>>> items = [1,2,3,4,5]
>>> squared = []
>>> for i in items:
...     squared.append(i**2)
... 
>>> squared
[1, 4, 9, 16, 25]

>>> def sqr(x): return x**2
... 
>>> map(sqr,items)
[1, 4, 9, 16, 25]

>>> map(lambda x: x**2,items)
[1, 4, 9, 16, 25]

>>> [ x**2 for x in items ]     #這個我最喜歡了,通常狀況下速度足夠快,並且可讀性強
[1, 4, 9, 16, 25]

條條大路通羅馬,以上方法,在編程中,本身根據須要來選用啦。

在以上感性認識的基礎上,在來瀏覽有關map()的官方說明,可以更明白一些。

map(function, iterable, ...)

Apply function to every item of iterable and return a list of the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. If one iterable is shorter than another it is assumed to be extended with None items. If function is None, the identity function is assumed; if there are multiple arguments, map() returns a list consisting of tuples containing the corresponding items from all iterables (a kind of transpose operation). The iterable arguments may be a sequence or any iterable object; the result is always a list.

理解要點:

  • 對iterable中的每一個元素,依次應用function的方法(函數)(這本質上就是一個for循環)。
  • 將全部結果返回一個list。
  • 若是參數不少,則對麼個參數並行執行function。

例如:

>>> lst1 = [1,2,3,4,5]
>>> lst2 = [6,7,8,9,0]
>>> map(lambda x,y: x+y, lst1,lst2)     #將兩個列表中的對應項加起來,並返回一個結果列表
[7, 9, 11, 13, 5]

請看官注意了,上面這個例子若是用for循環來寫,還不是很難,若是擴展一下,下面的例子用for來改寫,就要當心了:

>>> lst1 = [1,2,3,4,5]
>>> lst2 = [6,7,8,9,0]
>>> lst3 = [7,8,9,2,1]
>>> map(lambda x,y,z: x+y+z, lst1,lst2,lst3)
[14, 17, 20, 15, 6]

這才顯示出map的簡潔優雅。

預告:下一講詳解reduce和filter