1. 闭包
形式:函数作为返回值,高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def calc_sum(lst):
def lazy_sum():
return sum(lst)
return lazy_sum
f = calc_sum() //不会调用
f()
这里的calc_sum
可以进行字面理解为“懒求和”
当函数f
定义好了以后,实际上是定义了一个函数的实体。只有在f()
进行调用以后才进行了函数求和的功能。
闭包中有局部变量。
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
上述中的程序返回看似返回的结果是1, 4, 9。
而实际结果全部都为16。
这从闭包的特性上也可以理解。我们定义了一个函数的实体,在其f1(),f2(), f3()调用以后才进行了输出。这里他们都是单独的函数实体,内部的值互不影响。
2. 匿名函数(lambda)
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
例如我们使用一行代码就能打印出来1,20中所有的奇数。
print(list(filter(lambda x : x % 2 == 1, range(1, 20))))
找出一组数据中的非空数据。
print filter(lambda s: s and len(s.strip()) > 0, ['test', None, '', 'str', ' ', 'END'])
由上述的例子可以看出lambda极大的减少了代码量。
3. 装饰器(decorator)
Python的decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。
import time
def performance(f):
def log_time(x):
t1= time.time()
res = f(x)
t2=time.time()
print 'call %s() in %fs' % (f.__name__, (t2 - t1))
return res
return log_time
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
call factorial() in 0.002492s
3628800
@performance
在python中就是调用这个装饰器的关键字。在Java中也由类似的操作,Java中称之为注解。
当然这种高阶函数中也可以传入参数,当我们在做不通的装饰器时,返回不同的功能,最常用的就是各种logger
utl了。
import time
def performance(unit):
def performace_docorator(f):
def log_time(*args, **kwargs):
start_time = time.time()
res = f(*args, **kwargs)
end_time = time.time()
print("call %s() in %f%s" % (f.__name__, end_time - start_time, unit))
return res
return log_time
return performace_docorator
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
call factorial() in 0.002869ms
3628800
4.偏函数
当一个函数有很多参数时,调用者就需要提供多个参数。如果减少参数个数,就可以简化调用者的负担。
比如,int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换,但int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做 N 进制的转换:
functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85