第一個python高階函數:
示例:計算一個值的階乘(遞歸)
#!/usr/bin/env python
#coding=utf-8
def fact(n):
if n <= 1:
return n #遞歸函數必須有退出條件
return fact(n-1)*n #調用函數自身 最終格式爲return 2*3*4*5*6*7*8*9*10
f = fact(10) #python中函數遞歸最大深度爲1000
print f
執行結果:
[root@server24 ~]# ./func_9.py
3628800
在python中儘量避免遞歸,絕大多數都是可以轉爲迭代,因爲迭代要比遞歸快的多。
同樣利用迭代計算一個值的階乘:
def fact(n):
ret = 1 #設置初值
for i in range(n,1,-1):
ret *= i
return ret
print fact(10)
執行結果[root@server24 ~]# ./func_9.py
3628800
在python中函數是一等對象,可以像值一樣賦值,作爲函數的返回值返回。
高階函數
以函數對象作爲參數的函數叫高階函數:
下面爲三個內置的高階函數:
filter() 過濾: filter(function or none ,seq)當函數返回值爲true時,會將序列的當前值加進來
>>> li = [1,2,3,4,5,6,7]
>>> def f(x):
... return x % 2 == 0
...
>>> filter(f,li)
[2, 4, 6]
用高階函數手動實現內置filter函數
#!/usr/bin/env python
#coding=utf-8
li = [1,2,3,4,5,6,7]
def f(x):
return x % 2 == 0 #return出去的是布爾值 true or false
def afilter(f1,lis):
lii = list()
for i in lis:
if f1(i):
lii.append(i)
return lii
st = afilter(f,li)
print st
[root@server24 ~]# ./afilter.py
[2, 4, 6]
map() 映射:對列表中每個元素執行一個函數
>>> li = [2,3,4,5,6,7]
>>> def f(x):
... return x * 2
...
>>> map(f,li)
[4, 6, 8, 10, 12, 14]
用高階函數手動實現高階內置函數map()
#!/usr/bin/env python
#coding=utf-8
li = [1,2,3,4,5,6,7]
def f(x):
return x * 2
def amap(f1,lii):
lis = list()
for i in lii:
lis.append(f1(i))
return lis
st = amap(f,li)
print st
[root@server24 ~]# ./amap.py
[2, 4, 6, 8, 10, 12, 14]
reduce() 化簡:將每次迭代結果與下一個元素一同執行一個二元的func函數
>>> li = [2,3,4,5,6,7]
>>> def sum(x,y):
... return x * y
...
>>> reduce(sum,li)
5040
用高階函數手動實現內置reduce
#!/usr/bin/env python
li = [0,1,2,3,4]
def f(x,y):
return x * y
def reduc(f1,lis):
st = lis[0]
for i in range(1,len(lis)):
st = f1(st,lis[i])
return st
s = reduc(f,li)
print s
函數嵌套
嵌套一般格式:
def external():
def internal():
expression
return internal #返回爲嵌套,且與嵌套函數同級
示例:無參數函數嵌套
#!/usr/bin/env python
#coding=utf-8
def ext():
print 'this is external'
def internal():
print 'this is internal'
return internal
f = ext() #調用函數ext,將返回函數internal賦值給變量f
f() #實際調用的是嵌套函數
執行結果:
[root@server24 ~]# ./ext.py
this is external
this is internal
計算一個函數的執行時間
#!/usr/bin/env python
#coding:utf-8
import time
import datetime
def func(arg):
time.sleep(arg)
def timezo(fun):
def wrap(arg):
start = datetime.datetime.now()
fun(arg)
end = datetime.datetime.now()
cost = end - start
# **.total.seconds()用於計算秒數,是python2.7較之前版本新加的功能
print "execute %s spend %s" % (fun.__name__,cost.total_seconds())
return wrap
f = timezo(func) #返回函數wrap
f(3) #再次調用函數wrap
Decorator 裝飾器:其實也是一個函數,是用來包裝函數的函數。
作用:解耦
在使用裝飾器後返回一個修改之後的函數對象,將其重新賦值原來的標識符,並永久喪失對原始函數的訪問。將**.__name__,**.doc__等等改爲裝飾器內return的函數的屬性
如上計算函數執行時間的模塊其實就是一個裝飾器,一般用@來引用裝飾函數
示例:
#!/usr/bin/env python
#coding:utf-8
import time
import datetime
def deco(func):
'''第一個decorator是裝飾函數,它的參數用來加強裝飾的,其內部必須
建一個接受被裝飾函數的函數,然後返回這個對象'''
def new_deco(arg):
'''裝飾器裏面一般原封不動地調用函數,不影響函數本身'''
start = datetime.datetime.now()
func(arg)
end = datetime.datetime.now()
cost = end - start
print 'exeute %s spend %s' % (func.__name__,cost)
return new_deco #必須返回
@deco #在調用func函數之前引用裝飾器
def func(arg):
'''一切皆對象'''
time.sleep(arg)
func(2)
'''返回來的是修改後的函數對象,即爲裝飾器內return的函數的屬性'''
print func.__name__
print func.__doc__
執行結果:[root@server24 ~]# ./deco.py
exeute func spend 0:00:02.002529
new_deco
裝飾器裏面一般原封不動地調用函數,不影響函數本身
如果在使用裝飾器時總是丟失函數本身的屬性信息那將是很糟糕的事情,functools.wraps解決了這個問題,wraps在裝飾器中可以將函數的函數名,文檔字符串,參數信息等等複製過來
示例:#!/usr/bin/env python
#coding:utf-8
import time
import datetime
import functools #導入functools模塊
def deco(func):
'''第一個decorator是裝飾函數,它的參數用來加強裝飾的,其內部必須
建一個接受被裝飾函數的函數,然後返回這個對象'''
@functools.wraps(func)
def new_deco(arg):
'''裝飾器裏面一般原封不動地調用函數,不影響函數本身'''
start = datetime.datetime.now()
func(arg)
end = datetime.datetime.now()
cost = end - start
print 'exeute %s spend %s' % (func.__name__,cost)
return new_deco #必須返回
@deco #在調用func函數之前引用裝飾器
def func(arg):
'''一切皆對象'''
time.sleep(arg)
func(2)
'''返回來的是修改後的函數對象,即爲裝飾器內return的函數的屬性'''
print func.__name__
print func.__doc__
執行結果:[root@server24 ~]# ./deco.py
exeute func spend 0:00:02.002885
func
一切皆對象