python函數式編程之返回函數
高階函數處理可以接受函數作爲參數外,還可以把函數作爲結果值返回。
函數作爲返回值
def laxy_sum(*args): def sum(): ax = 0; for n in args: ax = ax + n; return ax; return sum; print(laxy_sum(1, 3, 5, 7)); # <function laxy_sum.<locals>.sum at 0x000001F2E3272F28>返回一個函數而不是一個值
在這個函數中,內部函數sum可以引用外部函數laxy_sum的參數和局部變量,當外部函數返回函數sum時,相關參數和變量都保存在返回的函數中,這種情況稱爲“閉包”個人覺得和JavaScript的閉包很相似,這種程序結構擁有極大的威脅。
當我們調用lazy_sum時,每次調用都會返回新的函數,即使傳入相同的參數。閉包
當一個函數返回了一個函數後,其內部的局部變量還被新函數引用。返回的函數並沒有立即執行,而是直到調用了外部函數才執行
python函數式編程之匿名函數
當我們在傳入函數時,有時候不需要顯式的定義函數,而是直接傳入匿名函數。
匿名函數就是沒有函數名的函數,python用關鍵字lambda表示匿名函數,冒號前面的x表示函數的參數
#匿名函數
p = list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6]));
print(p);
# [1, 4, 9, 16, 25, 36]
匿名函數有個限制,就是只能有一個表達式,不用寫return,返回值就是該表達式的結果。
python函數式編程之裝飾器
由於函數也是一個對象,函數對象也可以賦值給變量,所以我們可以通過變量也能調用函數。
def now():
print('2017-11-22');
f = now;
print(f());# 2017-11-22
函數對象有一個屬性name屬性,可以拿到函數的名字:像上面的例子就可以用 f.name取到函數的名字now
在代碼運行期間動態增加功能的方式,稱之爲“裝飾器”(Decorator)。如,在函數now調用前後自動打印日誌,但又不希望修改now()函數的定義。裝飾器本質上是一個幹返回函數的高階函數。
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__);
return func(*args, **kw);
return wrapper;
@log
def now():
print('2017-11-22');
print(now());
# call now():
# 2017-11-22
Python的@語法後續
python函數式編程之偏函數
簡單理解
如int()函數可以把字符串轉換成整數形式:print(int("1234"));#字符串轉換成整數
int函數還提供了base參數,用來把字符串轉換成N進制的數,默認是10.
print(int("12345", base=8));
但是當我們要進行很多的值轉換的時候,一個個傳入函數的話,就會很低效,那麼我們就可以編寫一個這樣的函數,讓他能實現我們的想法。
def int2(x, base=2): return int(x, base) print(int2("100001"));#33 print(int2("1101110"));#110
向上面這樣我們就不用多次輸入int(x, base=n),python的functools.partial就幫我們創建了一個偏函數,不需要我們編寫函數int2,可以直接創建一個int2函數:
#偏函數 import functools; int2 = functools.partial(int, base=2); print(int2("11101"));#29
所以,functools.partial的作用就是,把一個函數的某些參數設置默認值,返回個新的函數,調用這個新函數會更簡單。但也可以傳入其他的值,如:int2(“10010”, base=10);
總結
當我們函數參數個數很多,需要簡化時,我們可以使用python的functools.partial來創建一個偏函數來固定一些參數,使得我們在使用新函數的時候更加方便。