Python中的函數、裝飾器

  • map()函數接收兩個參數,一個是函數,一個是序列,map將傳入的函數依次作用到序列的每個元素,並把結果作爲新的list返回。
>>> s = ['AASDa', 'dendY']
>>> def formatStr(ss):
return ss[0].upper() + ss[1:len(ss)].lower()
 
>>> v = formatStr('aaaB')
>>> v
'Aaab'
>>> map(formatStr, s)
<map object at 0x000000000320A668>
>>> for v in map(formatStr, s):
print(v)
 
Aasda
Dendy

  • reduce把一個函數作用在一個序列[x1, x2, x3...]上,這個函數必須接收兩個參數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
>>> L = [2, 3, 4]
>>> def prod(a, b):
return a * b
>>>
>>> from functools import *
>>> reduce(prod, L)
24
>>>
  • filter函數,方法同map,目的是過濾list中符合條件的元素:
>>> s = [1, 2, -3, -5]
>>> def notLt0(x):
return x >= 0
 
>>> filter(notLt0, s)
<filter object at 0x000000000320A940>
>>> for v in filter(notLt0, s):
print(v)
 
1
2
>>>
如上的示例,定義一個notLt0的方法,該方法用於判斷元素是否大於等於0,是則返回True,否則返回False。而filter則會將列表s的每一個元素作爲參數調用notLt0方法,最後將所有返回True的元素重新組裝成一個list返回。
  • 匿名函數:無須定義函數的名稱,格式如下:
fn = lambda 函數參數列表: 函數體
其中fn爲返回的匿名函數,例如:
'''
匿名函數
'''
f = lambda x : x * x
print(f(2))
  • 函數的閉包,類似javascript的閉包,即外部函數返回內部函數的引用,內部函數可能持有外部函數變量的引用,例如:
'''
閉包
'''
def count():
fs = []
for i in range(1, 4):
def f():
print(i)
return i * i
fs.append(f)
return fs
 
f1, f2, f3 = count()
print('before execute...')
print(f1()) # 輸出:9
print(f2()) # 輸出:9
print(f3()) # 輸出:9
print('after execute...')
由於每次執行fn()時,i的值都變爲了3,所以輸出的結果並非預期的1,4,9,解決這種問題有多種方式,可以再定義一層閉包,也可以將fs中的元素修改爲f函數的執行結果,而不是函數引用。
  • 裝飾器(decorator),包裝目標函數,在不改變原目標函數的情況下,對其進行包裝,實現更多的功能。
    例如:實現一個打印日誌的裝飾器:
'''
裝飾器
'''
# 定義一個裝飾器(decorator)
def log(fn):
def wrapper(*args, **kw):
print('call : %s' % (fn.__name__))
return fn(*args, **kw)
return wrapper
 
@log
def func():
print ('hello!')
 
func()
其中,log函數爲一個裝飾器,除了完成fn函數本身的功能外,還添加了打印日誌的功能,log函數返回一個裝飾函數wrapper,打印的結果:
call : func
hello!
Python中使用@符號來表示裝飾器(不是java的註解,形式類似),在執行func函數時,解釋器看到@符號標識,會先執行log方法,並將func函數作爲參數,此時func函數依然存在,但是同名的func變量會指向wrapper函數:
print(func.__name__)
輸出wrapper,同:
func = wrapper(*args, **kw):
print('call : %s' % (fn.__name__))
return fn(*args, **kw)
所以,執行func()函數其實執行的是wrapper函數。

上邊爲最簡單的裝飾器,如果我們要實現可自定義參數的裝飾器呢?
# 自定義文本的裝飾器
def log(text):
def decorator(fn):
def wrapper(*args, **kw):
print('log : %s, function name : %s. ' % (text, fn.__name__))
fn(*args, **kw)
return wrapper
return decorator
 
@log('this is a log text.')
def func():
print ('hello!')
 
func()
print(func.__name__) # 輸出:wrapper
如上,我們需要再定義一個函數decorator來接收我們定義的參數信息,除了上邊的執行過程外,在調用func函數時,解釋器會先執行log和decorator函數,最後在執行wrapper函數,形式如下:
func = log(自定義參數)(func)
  • 偏函數,functools.partial,固定函數參數,形成新的函數:
如果我們需要在轉換爲int的時候確定進制,Python提供了int方法:
int(x, base = 10)
base爲此時x的進制數,默認爲10,我們寫一個將二進制字符串轉換爲int的方法:
def int2(x):
return int(x, base = 2)
s = int2('110')
print (s) # 輸出6
但是,其實Python已經爲我們做了這樣的事情,那就是利用functools.partial的方法:
int2 = functools.partial(int, base = 2)
s = int2('110')
print (s) # 輸出6
當然,該函數用法有很多,例如將max函數默認與一些元素比較:
max2 = functools.partial(max, 10, 20, 30)
s = max2(1, 2, 3, 40)
print(s) # 輸出:40
s = max2(1, 2, 3)
print(s) # 輸出:30
這樣,max函數在比較的元素中,默認會加入10,20,30了。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章