高阶函数
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
与js相似,与c#中的委托一相似。
- abs() 求一个数的绝对值
#模拟abs得到一个数的绝对值
def absFun(n):
if n<0:
return -n;
return n
- map(fn,list) 集合处理函数,作用到循环迭代对象的每个元素,返回新的对象
fn是逐个处理元素的函数
#将list值全部转换成字符串,str是一个函数(字符串转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是函数需要两个参数,结果会累积,求和会用到
reduce(lambda x,y:x*y,L)
int()转换成整数,float()转换成浮点数,sum()求和,.index('.')符号.首次出现的下标,.upper()转换成大写,.lower()转换成小写
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便捷函数
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()排序的关键在于实现一个映射函数。
#对字典姓名,第三个字母进行排序
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0][2]
闭包
在一个函数内部定义另一个函数,它可以调用外部函数的参数和局部变量,就形成了闭包
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)立刻被执行,因此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()中,但不会执行g函数,而是返回了函数g
- 函数count2返回的是一个集合,每个元素都是一个函数
执行结果:
>>> f1, f2, f3 = count2()
>>> f1()
1
>>> f2()
4
使用闭包和生成器结合起来,形成每次调用就+1的效果:
def createCounter():
def dizeng ():
a=1
while True:
yield a
a =a+ 1
def sd ():return next(g)#如果直接使用dizeng(),会导致多次执行该函数
g = dizeng()#函数执行了一次,所以内部变量a只声明了一次,结果是一个生成器
return sd#因调用方式,结果必须返回函数
#调用函数
counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
匿名函数
使用lambda x: x * x这样方式的就是一个匿名函数
x表示匿名函数的参数,:后面的是应用计算
- 与普通函数应用方式一样,都可以作为变量或返回值
- 因为没有名字,不必担心名称冲突的问题
- 只能有一个表达式,返回值就是表达式的结果
装饰器
在函数的上面添加@函数名 的形式就是装饰器
#定义了一个执行函数前,自动打印日志的功能函数
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
#定义一个应用函数
@log
def now():
print('2015-3-25')
- 执行now( )就相当于执行了log(now)( )
- 除了@log标记,就是一个闭包函数的应用
- 为了保持now函数的__name__属性不变,可以使用@functools.wraps(func)
import functools
def log(text):
def decorator(func):
@functools.wraps(func)#可保持得到的最终运行的函数__name__值仍是func的值
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
#定义一个应用函数
@log('execute')
def now():
print('2015-3-25')
- 以上定义了一个带参数的log函数
- 执行now( )就相当于执行了log('execute')(now)( )
偏函数
针对一些有默认值的函数,生成一个固定项的函数
如int(x,base=10)参数base默认是10,如下:
int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
生成了一个新的函数int2,调用int2(二进制字符串),得到十进制数字