Python中的函式也是一種物件,而且函式還是一等公民。函式能作為引數,也能作為返回值,這使得Python中的函式變得很靈活。想想前面兩篇中介紹的通過內嵌函式實現的裝飾器和閉包。
下面就介紹一下Python函式相關的一寫內容。
可變長度引數
在程式設計的過程中,可能會遇到函式引數個數不固定的情況,這時就需要使用可變長度的函式引數。在Python函式定義中,使用*和**符號分別指定元組(非關鍵字)和字典(關鍵字)作為引數。
非關鍵字變長引數(元組)
當函式被呼叫的時候,所有的引數都將值賦給了在函式宣告中對應的區域性變數,剩下的非關鍵字引數按照順序新增到一個元組中便於訪問。
可變長元組引數必須在位置和預設引數之後,所以使用可變長元組引數的函式形式一般如下(中括號表示可選引數),可變長元組引數前有一個”*”符號:
1 2 |
def funcName([fromal_args,] *tuple_grp_nonkw_args): pass |
看一個例子:
1 2 3 4 5 6 7 8 9 10 11 |
def argFunc(positional_arg, keyword_arg="foo", *tuple_grp_nonkw_args): print "positional_arg:", positional_arg print "keyword_arg:", keyword_arg for arg in tuple_grp_nonkw_args: print "additional_arg:", arg argFunc(3) print argFunc(3, 4) print argFunc(3, 4, "hello", "world") |
程式碼的輸出為:
關鍵字變長引數(字典)
除了上面的方式,Python還可以支援關鍵字變長引數,額外的關鍵字引數被放入了一個字典進行使用。
可變長字典引數必須是函式定義中的最後一個引數,所以使用可變長字典引數的函式形式一般如下(中括號表示可選引數),可變長字典引數前有一個”**”符號:
1 2 |
def funcName([fromal_args,] [*tuple_grp_nonkw_args,] **dict_grp_kw_args): pass |
看一個例子:
1 2 3 4 5 6 7 8 9 10 11 12 |
def argFunc(positional_arg, keyword_arg="foo", *tuple_grp_nonkw_args, **dict_grp_kw_args): print "positional_arg:", positional_arg print "keyword_arg:", keyword_arg for arg in tuple_grp_nonkw_args: print "additional non-keyword arg:", arg for argKey in dict_grp_kw_args.keys(): print "additional keyword arg: {'%s': %s}" %(argKey, dict_grp_kw_args[argKey]) argFunc(3, 4, name="wilber", age=28) print argFunc(3, 4, "hello", "world", name="wilber", age=28) print |
程式碼輸出為:
函式呼叫的完整形式為:
func( positional_args, keyword_args, *tuple_grp_nonkw_args, **dict_grp_kw_args )
在使用的過程中,所有引數都是可選的,但應當注意的是:上面四種引數的位置是不可調換的。
匿名函式(lambda)
Python允許使用lambda關鍵字建立匿名函式,通過lambda關鍵字,可以快速編寫簡單函式。
使用lambda關鍵字的形式為:
1 |
lambda [arg1 [, arg2, ... argN]]: expression |
對於不經常被呼叫的簡單函式,建議直接使用lambda表示式,方便簡潔:
1 2 3 |
addNum = lambda x, y: x+y print addNum print "3 + 4 = ", addNum(3, 4) |
幾個內建函式
Python可以很好的支援物件導向程式設計,但是通過Python中以下幾個內建函式和lambda表示式,也可以體驗一下函數語言程式設計。
filter()
filter函式的完整形式為filter(func, seq):呼叫一個布林型別的函式func來遍歷每一個seq中的元素,返回一個使func返回值為ture的元素的序列。
例如獲取100以內的奇數:
1 |
print filter(lambda n: (n%2) == 1, range(100)) |
當然對於上面的例子,也可以使用列表解析實現:
1 |
print [i for i in range(100) if i%2 == 1] |
map()
map函式的完整形式為map(func, seq1 [, seq2…]):將函式func作用於給定序列的每一個元素,並用一個列表來提供返回值;如果func為None,作用同zip()。
是不是被上面的描述搞暈了,還是看例子吧:
1 2 3 4 5 6 7 8 9 |
# map的func為None print map(None, [4, 5, 6]) print map(None, [1, 2, 3], [4, 5, 6]) # map 針對一個序列 print map(lambda x: x*2, [4, 5, 6]) # map 針對多個序列 print map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6]) |
程式碼輸出為:
reduce()
reduce函式的完整形式為reduce(func, seq [, init]):func是一個二元函式;reduce對seq中的每一個元素進行迭代,每次迭代將上一次的迭代結果(第一次時使用init,如沒有init,則使用seq的第一個元素)與下一個元素執行func函式。
看一個例子,通過reduce函式進行求和操作:
1 2 |
print reduce(lambda x, y: x + y, range(10)) print reduce(lambda x, y: x + y, range(10), 100) |
輸出為:
根據上面的介紹,我們自己也可以實現一個reduce函式:
1 2 3 4 5 6 7 8 9 |
def xreduce(bin_func, seq, init=None): Iseq = list(seq) if init is None: res = Iseq.pop(0) else: res = init for obj in Iseq: res = bin_func(res,obj) return res |
總結
本文介紹了Python函式相關的一些內容:
- 可變長引數
- 匿名函式lambda
- 內建函式filter(),map(),reduce