函数式编程的理解
函数本身也是变量,可以吧函数本身作为参数传入另一个函数,还允许返回一个函数。
高阶函数
map
映射,map(fun, iterable)
fun
为映射规则 iterable
为可迭代的变量。
例如,将[1, 2, 3…9]转化为[1, 4, 9, … 81]
#可以使用生成序列
[x*x for x in range[1, 10]]
#现在使用map
def f(x):
return x*x
r = map(f, [1,2,3,4,5,6,7,8,9]) #注意返回值为iterator
list(r) #转化为list
reduce
按照序列,操作两个数,依次进行,值作为后面的参数。
reduce(fun, iterable)
fun
为函数,要有两个参数 iterable
为可迭代的变量。
例如 计算sum
def add(x, y):
return x + y
reduce(add, [1, 3, 5, 7, 9])
filter
过滤器,返回也是一个iterator
格式filter(fun, iterable)
fun
的返回值是一个布尔,True
保留,False
被过滤掉。
def is_odd(n):
return n % 2 == 1
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) #filter的返回值为iterator,这里加一层list()转化为list
sorted
对list
进行排序。
格式:sorted(iterable, /, *, key=None, reverse=False)
key
函数,参数为iterable
的一项,返回值为数字
或string
.数字
和string
在python中都是可排序的
L = [-21, -12, 5, 9, 36]
sorted(L) #自然排序,[5, 9, -12, -21, 36]
sorted(L, key=abs) #按绝对值排序,[5, 9, -12, -21, 36]
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
def by_name(t):
return t[0]
L2 = sorted(L, key=by_name) #按照名字排序
闭包
函数返回值,可以是函数。
内部函数
可以引用外部函数
的参数和局部变量,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f = lazy_sum(1, 3, 5, 7, 9) #这里f是一个函数
f() #返回调用f()
返回函数不要引用任何
循环变量
,或者后续会发生变化的变量
。因为闭包是使用时调用,后面就会有很大的不确定性。
匿名函数
关键字lambda
表示匿名函数,冒号前面表示函数参数。只能有一个表达式,不用写return,返回值就是该表达式的结果。
def f(x):
return x * x
#等价于
lambda x:x*x
装饰器
装饰器,用来在原函数的基础上,包装一层。常用来打印log
def log(func):
@functools.wraps(func) #防止原函数__name__属性被修改
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
#装饰器的使用,像Java注解
@log
def now():
print('2015-3-25')
#也有带参数的装饰器,实现要包裹二层,详见参考资料
另外,还有一种类装饰器,可实现一样效果。
类装饰器主要依赖于函数__call__()
,每当你调用一个类的示例时,函数__call__()
就会被执行一次。
#类装饰器主要依赖于函数__call__(),
# 每当你调用一个类的示例时,函数__call__()就会被执行一次。
class Count:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kw):
self.num_calls += 1
print('num of calls is: {}'.format(self.num_calls))
return self.func(*args, **kw)
@Count
def example():
print('hello world')
if __name__ == '__main__':
example()
example()