Python 中的闭包、匿名函数、decorator 装饰器与python的偏函数
Python中的閉包
def calc_sum(lst):def lazy_sum():return sum(lst)return lazy_sum像這種內層函數引用了外層函數的變量(參數也算變量),然后返回內層函數的情況,稱為閉包(Closure)。在函數內部定義的函數和外部定義的函數是一樣的,只是他們無法被外部訪問。
閉包的特點是返回的函數還引用了外層函數的局部變量,所以,要正確使用閉包,就要確保引用的局部變量在函數返回后不能變。
def count():fs = []for i in range(1, 4):def f(i): # 必須傳入參數,生成局部變量,否則調用外層函數變量可變return lambda: i*i # 返回一個匿名函數,也叫 lambda單行表達式fs.append(f(i))return fs f1, f2, f3 = count() print f1(), f2(), f3()匿名函數
上述代碼中lambda表達式表示簡單的單行函數,方便定義,并且只在函數內部定義使用。
lambda 表達式必須使用 lambda 關鍵字進行定義。在 lambda 關鍵字之后、冒號左邊的是參數列表,可以沒有參數,也可以有多個參數。如果有多個參數,則需要用逗號隔開,冒號右邊是該 lambda 表達式的返回值。
匿名函數有個限制,就是只能有一個表達式,不寫return,返回值就是該表達式的結果。
函數返回時也可以返回匿名函數,如:
myabs = lambda x: -x if x < 0 else x myabs(-1) # 1decorator 裝飾器
當需要給原函數 f 增加功能時,不需要直接修改原函數。Python的 decorator 本質上就是一個高階函數,它接收一個函數作為參數,然后,返回一個新函數。
高階函數參考:https://blog.csdn.net/Qianzhen_Sun/article/details/105345949
使用 decorator 時,用Python提供的 @ 語法,這樣可以避免手動編寫 f = decorate(f) 這樣的代碼。徹底屏蔽原函數功能。
舉例:
要讓 @log 自適應任何參數定義的函數,可以利用 Python 的 *args (可變參數,返回一個 tuple)和 **kw (關鍵字參數,返回一個 dict),保證任意個數的參數總是能正常調用:
def log(f):def fn(*args, **kw):print 'call ' + f.__name__ + '()...'return f(*args, **kw)return fn編寫帶參數的 decorator:
def log(prefix): # 傳入參數def log_decorator(f):def wrapper(*args, **kw):print '[%s] %s()...' % (prefix, f.__name__)return f(*args, **kw)return wrapperreturn log_decorator@log('DEBUG') def test():pass print test()上面的調用等同于帶參數的log函數首先返回一個decorator函數,再讓這個decorator函數接收my_func并返回新函數。不利用@,拆開調用形式如下:
log_decorator = log('DEBUG') @log_decorator def test():pass print test()完善 decorator:
decorator 改變了函數名,還改變了函數的__doc__等其它屬性。如果要讓調用者看不出一個函數經過了@decorator的“改造”,就需要把原函數的一些屬性復制到新函數中:
def log(f):def wrapper(*args, **kw):print 'call...'return f(*args, **kw)wrapper.__name__ = f.__name__ # 原函數信息復制過來wrapper.__doc__ = f.__doc__return wrapper這樣寫 decorator很不方便,因為我們也很難把原函數的所有必要屬性都一個一個復制到新函數上,所以 Python內置的functools可以用來自動化完成這個“復制”的任務:
import functools def log(f):@functools.wraps(f) # 完成復制任務def wrapper(*args, **kw):print 'call...'return f(*args, **kw)return wrapperPython 的偏函數
functools.partial可以把一個參數多的函數變成一個參數少的新函數,少的參數需要在創建時指定默認值,這樣,新函數調用的難度就降低了。
自定義轉換2進制函數:
def int2(x, base=2):return int(x, base)可以通過 functools.partial 函數進行轉化:
import functools int2 = functools.partial(int, base=2) import functools # 自定義忽略大小寫排序 sorted_ignore_case = functools.partial(sorted, key=str.lower) print sorted_ignore_case(['bob', 'about', 'Zoo', 'Credit'])整理不易,點贊支持!
總結
以上是生活随笔為你收集整理的Python 中的闭包、匿名函数、decorator 装饰器与python的偏函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拔火罐是什么原理 拔火罐能去除湿气吗
- 下一篇: Python中的模块和包:模块的(动态)