函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。
(一)高阶函数
把函数作为参数传入,这样的函数称为高阶函数。
- 变量可指向函数
函数本身可以赋值给变量,即:变量可指向函数
f = abs
print(f(-10))
- 函数名也是变量
函数名其实是指向函数的变量
-传入函数
函数的参数可以接收变量,一个函数可以接收另一个函数作为参数,这种函数称为高阶函数。
def sum(a,b,f):
return f(a)+f(b)
1、map/reduce
map()和reduce()函数。map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
- map
# map
def f(x):
return x * x
r = map(f,[1,2,3,4,5])
print(list(r))
map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单f(x)=x2,还可以计算任意复杂的函数。
x = [1,2,3,4,5,6,7]
print(list(map(str,x)))
- reduce
reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。
# reduce
# 对序列求和
def add(x, y):
return x + y
sum = reduce(add, [1, 2, 3, 4, 5])
print(sum)
# 把序列[1, 2, 3, 4, 5]变换成整数12345
def fn(x, y):
return x * 10 + y
num = reduce(fn, [1, 2, 3, 4, 5])
print(num)
2、filter
过滤序列,和map()类似,filter()也接收一个函数和一个序列。filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。
# filter
# list中。删掉偶数,保留奇数
def is_qi(x):
return x % 2 == 1
l = list(filter(is_qi, [1, 2, 3, 4, 5, 6, 7, 8]))
print(l)
# 序列中空字符串删掉
def not_empty(s):
return s and s.strip()
s = list(filter(not_empty,['a','','b',None,'c',' ']))
print(s)
3、sorted
sorted()函数就可以对list进行排序,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序。
# 排序算法
# sorted
l = sorted([3, 1, 2, 43, 12])
print(l)
# 按绝对值大小排序
abs = sorted([21, 2, 32, -23, -12], key=abs)
print(abs)
# 忽略大小写,按照字母序排序
st = sorted(['bob', 'Asd', 'Coo', 'dss'], key=str.lower)
print(st)
# 反向排序 reverse=True
s = sorted(['bob', 'Asd', 'Coo', 'dss', 'Ds'], key=str.lower, reverse=True)
print(s)
# 按名字排序
L = [('Bob', 75, 2), ('Adam', 92, 3), ('Bart', 66, 1), ('Lisa', 88, 4)]
# 按名字排序
def sorted_byName(t):
t = t[0]
return t
# 按成绩排序
def sorted_byScore(t):
t = t[1]
return t
# 按学号排序
def sorted_byNo(t):
t = t[2]
return t
L1 = sorted(L, key=sorted_byName)
print(L1)
L2 = sorted(L1, key=sorted_byScore)
print(L2)
L3 = sorted(L2, key=sorted_byNo)
print(L3)
(二)返回函数
把函数作为结果值返回。
# 可变参数求和
def c_sum(*args):
a = 0
for i in args:
a = a + i
return a
print(c_sum(1, 2, 3, 4))
# 返回求和函数
def return_sumFun(*args):
def sum():
a = 0
for i in args:
a = a + i
return a
return sum
f1 = return_sumFun(1, 2, 3, 4, 5)
f2 = return_sumFun(1, 2, 3, 4, 5)
print(f1 == f2)
print(f1)
print(f1())
闭包:当一个函数返回了一个函数后,其内部的局部变量还被新函数引用
# 利用闭包返回一个计数器函数,每次调用它返回递增整数
def createCounter():
count = [0]
def counter():
count[0] += 1
return count[0]
return counter
countFun = createCounter()
print(countFun(),countFun(),countFun())
(三)匿名函数
在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
【匿名函数】 : lambda x: x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数,只能有一个表达式,不用写return。匿名函数也是一个函数对象,可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
# lambda
# 计算f(x)=x*x
def f(x):
return x * x
n = f(2)
print(n)
# 匿名函数
n = lambda x: x * x
print(n(2))
# 匿名函数作为返回值
def bt(x, y):
return lambda: x * x + y * y
f = bt(1, 3)
print(f())
l = list(filter(lambda n: n % 2 == 1, range(1, 20)))
print(l)
(四) 装饰器
在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator),decorator就是一个返回函数的高阶函数。
def log(func):
def wrapper(*args, **kw):
print('call %s():' %func.__name__)
return func(*args, **kw)
return wrapper
# @log放到now()函数的定义处,相当于执行了语句:now = log(now)
@log
def now():
print('2020:2:24')
print(now())
(五) 偏函数
functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。
- int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换。
# int
print(int('12345'))
# int() base参数 默认值10 N进制转换
print(int('100', base=8))
# 转二进制字符串
def int2(x, base=2):
return int(x, base)
print(int2('1000'))
- functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2。
# 偏函数
import functools
int2 = functools.partial(int, base=2)
print(int2('1000'))
functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。