函数式编程
定义
函数式编程是一种编程范式,将电脑运算视为函数的计算
特点
- 把计算视为函数
- 代码简洁方便阅读容易理解
- 允许有变量
- 支持高阶函数(函数作为变量)、闭包(返回函数)和匿名函数
使用
# 将函数作为参数
import math
def add(x, y, f):
return f(x) + f(y)
print(add(-1, 9, abs)) # ==> 10
print(add(4, 16, math.sqrt)) # ==> 6.0
'''map()函数
接收一个函数f和一个list,并依次把函数f作用在list的每个元素上,同时返回一个迭代器,可以依次迭代得到原来list元素处理后的结果
'''
def formatter(x):
return x[0].upper() + x[1:].lower()
for item in map(formatter, ['john', 'TIMY', 'DaniEl']):
print(item) # ⇒ John Timy Daniel
'''reduce()函数
接收一个函数f和一个list,对list的每个元素反复调用函数f,并返回最终结果,可以接收第三个参数作为初始值
Python2中可以直接使用,Python3中需要在functools包中引入
'''
from functools import reduce
def f(x, y):
return x * y
print(reduce(f, [1, 3, 5, 7, 9])) # ⇒ 945
'''filter()函数
接收一个函数f和一个list,通过函数f对每个元素进行判断,返回True或False,filter()根据判断结果自动过滤掉不符合条件的元素并返回一个迭代器,可以迭代出所有符合条件的元素
'''
import math
def is_integer(x):
r = int(math.sqrt(x))
return math.pow(r, 2) == x
for item in filter(is_integer, range(1,101)):
print(item) # ⇒ 1 4 9 16 25 36 49 64 81 100
'''sorted()函数
默认从小到大进行排序,当list每一个元素是容器时,则会以第一个元素来排序,返回一个新的list
如果需要指定排序的字段,key参数值是一个函数,接收待排序列表的元素作为参数并返回对应需要排列的字段
如果需要倒序,则需要指定reverse参数为True
'''
def k(item):
return item.lower()
name = ['boom', 'about', 'Dog', 'Large']
print(name) # ⇒ ['boom', 'about', 'Dog', 'Large']
newName = sorted(name, key=k)
print(newName) # ⇒ ['about', 'boom', 'Dog', 'Large']
'''返回函数
在函数内部可以定义子函数,同时可以把子函数返回
返回函数时不能带括号,返回函数值时则需要
'''
from functools import reduce
def f(x, y):
return x * y
def calc_prod(list_):
def prod():
return reduce(f, list_, 1)
return prod
p = calc_prod([1,2,3,4,5])
print(p()) # ⇒ 120
'''闭包
内层函数引用了外层函数的变量,并返回内层函数的结果
注意:返回函数不要引用任何循环变量或者后续会发生变化的变量
'''
def count():
fs = []
for i in range(1, 4):
def f(j):
def g():
return j * j
return g
k = f(i)
fs.append(k)
return fs
f1, f2, f3 = count()
print(f1(), f2(), f3()) # ⇒ (1, 4, 9)
'''匿名函数
匿名函数使用lambda关键字进行定义,lambda x,y: x + y,就可以完成函数的定义,冒号前表示匿名函数的参数,冒号后则是一个表达式,不用写return,返回值就是该表达式的结果
'''
name = ['boom', 'about', 'Large', 'Dog']
print(sorted(name, key=lambda x:x.lower())) # ⇒ ['about', 'boom', 'Dog', 'Large']
''''无参数的decorator
本质上是一个高阶函数,接收一个函数作为参数,返回一个新函数
使用@语法,可以避免手动编写代码
'''
# 只含一个参数
def log(f):
def fn(x):
print('call ' + f.__name__ + '()...')
return f(x)
return fn
# 含有任意个参数
def log(f):
def fn(*args, **kwargs):
print('call ' + f.__name__ + '()...')
return f(*args, **kwargs)
return fn
# 输出函数运行时间
import time
def performance(f):
def fn(*args, **kwargs):
t1 = time.time()
r = f(*args, **kwargs)
t2 = time.time()
print('call %s() in %fs' % (f.__name__, (t2-t1)))
return r
return fn
@performance
def add(x, y):
return x + y
add(1, 2) # ⇒ call add() in 0.000003s 3
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
factorial(10) # ⇒ call factorial() in 0.004084s
'''有参数的decorator
带参数的decorator首先返回一个decorator函数,再让这个decorator函数接收一个函数并返回新函数,相当于是在原有的二层函数里面,增加了一层嵌套
'''
import time
def performance(param):
def performance_decorator(f):
def fn(*args, **kwargs):
t1 = time.time()
r = f(*args, **kwargs)
t2 = time.time()
if param == 's':
print('call %s() in %fs' % (f.__name__, (t2-t1)))
if param == 'ms':
print('call %s() in %fms' % (f.__name__, (t2-t1)*1000))
return r
return fn
return performance_decorator
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
factorial(10) # ⇒ call factorial() in 3.329039ms call factorial() in 0.003894s
'''偏函数
创建一个调用另外一个部分参数或变量已经预置的函数
partial可以将参数多的函数变成参数少的新函数,缺的参数需要指定默认值
'''
from functools import partial
sorted_ignore_case = partial(sorted, key=lambda x: x.lower())
print(sorted_ignore_case(['boom', 'about', 'Large', 'Dog'])) # ⇒ ['about', 'boom', 'Dog', 'Large']