零基礎入門Python3-函數式編程(4)
一、裝飾器(decorator)
當我們定義好一個函數的時候,還想為函數添加一些功能,但是不想改變已經函數。這個時候,我們就可以使用裝飾器,為定義好的函數添加功能,且不修改函數中的代碼,是非常好用的一個方法。這裏要註意一下,所謂的添加功能,指的是在函數執行前或執行完後添加功能。
# 實例1,定義一個函數,輸入字符串"python"
def func():
print(‘python‘)
func()
>>> python
如果我們想在字符串 "python" 前面添加另外一個字符串 "hello"
# 實例2
def add(func):
print(func.__name__)
# xxx.__name__ 代表的是取函數名稱,這裏是取func1的函數名稱
def f():
print("hello")
# 在func1函數運行前,打印出 "hello"
func()
# 運行 func1,這裏已經把 fun1賦值給變量func了
return f
# 這裏是一個返回函數
@add
# 在定義函數的前一行使用python的 @ 符號,等於執行了 func1 = add(func1)
def func1():
print(‘python‘)
func1()
print(func1.__name__)
# 再一次輸出 func1 的函數名稱
>>> func1
hello
python
f
# 因為函數 f 作為返回函數,func1 在函數 f 中執行,所以 func1 函數賦給了 函數 f,所以,函數的名稱會發生變化。
我們看看裝飾器的局限性
# 實例3
def add(func):
def f1():
print(‘+ add qian mian‘)
func()
print(‘+ add hou mian‘)
return f1
@add
def f2():
print(‘zhe shi han shu de gong neng‘)
f2()
>>> + add qian mian
zhe shi han shu de gong neng
+ add hou mian
# 這個實例說明了,我們只能往函數執行前或者執行後的地方添加功能。
當我們想往附加的函數中傳入參數的時候,必須另外嵌套一個函數,以此傳入參數。
# 實例4
def addtext(text1,text2):
def add(func):
def f1():
print(‘+ add {0}‘.format(text1))
func()
print(‘+ add {0}‘.format(text2))
return f1
return add
@addtext(‘aaaa‘,‘bbbb‘)
def f2():
print(‘zhe shi han shu de gong neng‘)
f2()
>>> + add aaaa
zhe shi han shu de gong neng
+ add bbbb
# 當我們要傳入參數值的時候,在 @函數名的後面附加一個圓括號,並帶入參數。@addtext(‘aaaa‘,‘bbbb‘) 等同於 f2=addtext(‘aaaa‘,‘bbbb‘)(f2)
# f2=addtext(‘aaaa‘,‘bbbb‘)(f2) ,首先執行的是 addtext(‘aaaa‘,‘bbbb‘),然後執行 add(f2)......
我們在實例3中出現一個函數名稱會變化的問題,我們該怎麽解決呢?使用 functools.wraps
# 實例5
import functools
# 導入functools模塊
def add(func):
print(func.__name__)
@functools.wraps(func)
def f():
print(‘addtext‘)
func()
return f
# 開始定義函數 f1
@add
def f1():
print(‘python‘)
f1()
print(f1.__name__)
# 首先導入functools函數,利用@functools.wraps(func) 來解決函數名變化的問題。切記不要使用 f.__name__=func.__name__
二、偏函數
當我們要經常使用 int 進行二進制轉換為十進制的時候,會用到 print(int(‘100011‘,2)) 。但是如果每次進行轉換的時候,都要對 int 的參數base賦值,這樣是很麻煩。那怎麽解決呢?
# 實例1
def _int(n,base=2):
return (n,base)
_int(1010101)
>>> 35
# 這是一種解決辦法,重新定義一個函數。
但是,python 的模塊 functools.partial 可以幫我們創建一個偏函數,省去了自定義函數的麻煩
functools.partial(函數名稱,參數)
- 作用就是相當於把參數給固定了,不用每次都給賦值
# 實例2
import functools
_int=functools.partial(int,base=2)
print(_int(‘101011‘))
>>> 43
偏函數可以傳入函數對象、*args和**kw這3個參數
# 實例3
import functools
s=functools.partial(max,1123)
print(s(666,22))
>>> 1123
# functools.partial(max,1123)中,1123 以參數的形式傳入max函數中,並進行運算。
關註公眾號,了解更多!# 實例4
import functools
k={‘base‘:2}
_int=functools.partial(int,**k)
print(_int(‘10101‘))
# functools.partial 接收了 **kw 參數
零基礎入門Python3-函數式編程(4)