1. 程式人生 > >python-函數及高階函數

python-函數及高階函數

位置參數 9.png 簡化 定義函數 2層 global sun 根據 .com

函數中return默認返回None,若指定了多個返回值,則封裝成一個元組

函數參數

參數定義的順序必須是:必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。
def person(name, age=18, *args, city, **kw):

默認參數一定要用不可變對象,如果是可變對象,程序運行時會有邏輯錯誤!
可變參數*args既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過*args傳入:func(*(1, 2, 3));
關鍵字參數**kwargs既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過**kw傳入:func(**{‘a‘: 1, ‘b‘: 2})。
命名的關鍵字參數是為了限制調用者可以傳入的參數名,同時可以提供默認值。定義命名的關鍵字參數在沒有可變參數的情況
下不要忘了寫分隔符*,否則定義的將是位置參數。(未知參數?)(所以命名的關鍵字參數是一種特殊的關鍵字參數)

有多個默認參數時,調用的時候,既可以按順序提供默認參數,也可以不按順序提供部分默認參數。

作用域(搜索優先級順序:LEGB)

local,局部作用域,即函數中的變量
enclosing,嵌套的腹肌函數的局部作用域,即包含此函數的上級函數的局部作用域,但不是全局的
global,全局變量,就是模塊級別定義的變量
built-in,系統固定模塊裏的變量

遞歸函數

遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
解決遞歸調用棧溢出的方法是通過尾遞歸優化,事實上尾遞歸和循環的效果是一樣的,所以,把循環看成是一種特殊的尾遞歸函數也是可以的。
尾遞歸是指,在函數返回的時候,調用自身本身,並且,return語句不能包含表達式。
遺憾的是,大多數編程語言沒有針對尾遞歸做優化,Python解釋器也沒有做優化,所以,即使把上面的fact(n)函數改成尾遞歸方式,也會導致棧溢出。
實驗結果:遞歸不能超出997層?

但凡遞歸可以寫的程序,循環都可以解決。
遞歸的效率很低

lambda表達式

lambda表達式,通常是在需要一個函數,但是又不想費神去命名一個函數的場合下使用,也就是指匿名函數。
# 定義函數(lambda表達式)冒號前面是參數,冒號後面是返回值,返回值可以是表達式;無中間過程
my_lambda = lambda arg : arg + 1

高階函數

把函數作為參數傳入,這樣的函數稱為高階函數,函數式編程就是指這種高度抽象的編程範式。
map/reduce/filter
高階函數除了可以接受函數作為參數外,還可以把函數作為結果值返回。

閉包

一般情況下,我們定義一個函數。調用該函數時,會結果一系列計算,返回最終結果。

但是有時我們不需要立刻求和,而是在後面的代碼中,根據需要在計算怎麽辦
這時可以定義2層函數,外層函數返回值為內層函數的函數名---這就是閉包
註意:調用外層函數返回內層函數名時,外層函數的相關參數和變量都已經保存在了返回的內層函數中
每次調用外層函數返回的內層函數都是不同的,即使外層函數的參數變量完全一致

閉包函數:2個條件
1,一個函數中定義有一個內部函數
2,這個內部函數對外部函數的變量進行引用

簡單來說就是閉包函數作為一個內部函數,卻可以在全局被調用

技術分享圖片

裝飾器

本質上,decorator(裝飾器)就是一個返回函數的高階函數。
把@log放到now()函數的定義處,相當於執行了語句:now = log(now)

有時需要把原始函數的__name__等屬性復制到wrapper()函數中,否則,有些依賴函數簽名的代碼執行就會出錯。
不需要編寫wrapper.__name__ = func.__name__這樣的代碼,Python內置的functools.wraps就是幹這個事的

裝飾器,加深理解:對一個函數增加了計時功能,同時還是用原函數實現
import time
def outer(aaa):
def inner():
start = time.time()
aaa()
time.sleep(2)
sun1 = time.time() - start
return sun1
return inner
@outer #與abc = outer(abc)完全等價,但是在原定義函數的上方
def abc():
print(‘輸出是:‘)

abc = outer(abc)
print(abc)
print(abc())

偏函數

functools.partial就是幫助我們創建一個偏函數的,
int2 = functools.partial(int, base=2)
與下面的等效
def int2(x, base=2):
return int(x, base)
簡單總結functools.partial的作用就是,把一個函數的某些參數給固定住(也就是設置默認值),返回一個新的函數,調用這個新函數會更簡單。
當函數的參數個數太多,需要簡化時,使用functools.partial可以創建一個新的函數,這個新函數可以固定住原函數的部分參數,從而在調用時更簡單。

python-函數及高階函數