高階函數(shù)
把函數(shù)作為參數(shù)傳入疲扎,這樣的函數(shù)稱為高階函數(shù)昵时,函數(shù)式編程就是指這種高度抽象的編程范式。
與js相似椒丧,與c#中的委托一相似壹甥。
- abs() 求一個數(shù)的絕對值
#模擬abs得到一個數(shù)的絕對值
def absFun(n):
if n<0:
return -n;
return n
- map(fn,list) 集合處理函數(shù),作用到循環(huán)迭代對象的每個元素壶熏,返回新的對象
fn是逐個處理元素的函數(shù)
#將list值全部轉(zhuǎn)換成字符串,str是一個函數(shù)(字符串轉(zhuǎn)int使用int())
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']
#首字母大小句柠,其他小寫,處理map的示例
def normalize(name):
return name[0].upper()+name[1:].lower()
#等同于
lambda name:name[0].upper()+name[1:].lower()
- reduce(fn,list) fn是函數(shù)需要兩個參數(shù)棒假,結(jié)果會累積溯职,求和會用到
reduce(lambda x,y:x*y,L)
int()轉(zhuǎn)換成整數(shù),float()轉(zhuǎn)換成浮點數(shù)帽哑,sum()求和缸榄,.index('.')符號.首次出現(xiàn)的下標,.upper()轉(zhuǎn)換成大寫祝拯,.lower()轉(zhuǎn)換成小寫
def str2float(s):
n=s.index('.')
s=s[:n]+s[n+1:]
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def char2num(x):
return DIGITS[x]
return reduce(lambda x,y:10*x+y,map(char2num,s))/(10**(len(s)-n))
- filter() 篩選過濾元素
標準的寫法:
def not_empty(s):
return s and s.strip()
list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))
使用lambda便捷函數(shù)
def _not_divisible(n):
return lambda x : x%n > 0
#等價于:
def _not_divisible(n):
def suibian(x):
return x%n>0
return suibian
- sorted()排序算法
對集合排序,忽略大小寫她肯,反向
>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
['Zoo', 'Credit', 'bob', 'about']
用sorted()排序的關(guān)鍵在于實現(xiàn)一個映射函數(shù)佳头。
#對字典姓名,第三個字母進行排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0][2]
閉包
在一個函數(shù)內(nèi)部定義另一個函數(shù)晴氨,它可以調(diào)用外部函數(shù)的參數(shù)和局部變量康嘉,就形成了閉包
def count2():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被執(zhí)行,因此i的當前值被傳入f()
return fs
#使用lambda簡化
def count3():
fs = []
for i in range(1, 4):
def f(j):
return lambda: j*j
fs.append(f(i))
return fs
- 在count2中j的值被傳入f()中籽前,但不會執(zhí)行g(shù)函數(shù)亭珍,而是返回了函數(shù)g
- 函數(shù)count2返回的是一個集合敷钾,每個元素都是一個函數(shù)
執(zhí)行結(jié)果:
>>> f1, f2, f3 = count2()
>>> f1()
1
>>> f2()
4
使用閉包和生成器結(jié)合起來,形成每次調(diào)用就+1的效果:
def createCounter():
def dizeng ():
a=1
while True:
yield a
a =a+ 1
def sd ():return next(g)#如果直接使用dizeng()肄梨,會導(dǎo)致多次執(zhí)行該函數(shù)
g = dizeng()#函數(shù)執(zhí)行了一次阻荒,所以內(nèi)部變量a只聲明了一次,結(jié)果是一個生成器
return sd#因調(diào)用方式众羡,結(jié)果必須返回函數(shù)
#調(diào)用函數(shù)
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
匿名函數(shù)
使用lambda x: x * x這樣方式的就是一個匿名函數(shù)
x表示匿名函數(shù)的參數(shù)侨赡,:后面的是應(yīng)用計算
- 與普通函數(shù)應(yīng)用方式一樣,都可以作為變量或返回值
- 因為沒有名字粱侣,不必擔心名稱沖突的問題
- 只能有一個表達式羊壹,返回值就是表達式的結(jié)果
裝飾器
在函數(shù)的上面添加@函數(shù)名 的形式就是裝飾器
#定義了一個執(zhí)行函數(shù)前,自動打印日志的功能函數(shù)
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
#定義一個應(yīng)用函數(shù)
@log
def now():
print('2015-3-25')
- 執(zhí)行now( )就相當于執(zhí)行了log(now)( )
- 除了@log標記齐婴,就是一個閉包函數(shù)的應(yīng)用
- 為了保持now函數(shù)的__name__屬性不變油猫,可以使用@functools.wraps(func)
import functools
def log(text):
def decorator(func):
@functools.wraps(func)#可保持得到的最終運行的函數(shù)__name__值仍是func的值
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
#定義一個應(yīng)用函數(shù)
@log('execute')
def now():
print('2015-3-25')
- 以上定義了一個帶參數(shù)的log函數(shù)
- 執(zhí)行now( )就相當于執(zhí)行了log('execute')(now)( )
偏函數(shù)
針對一些有默認值的函數(shù),生成一個固定項的函數(shù)
如int(x,base=10)參數(shù)base默認是10柠偶,如下:
int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
生成了一個新的函數(shù)int2情妖,調(diào)用int2(二進制字符串),得到十進制數(shù)字