Python基础语法之 函数式编程
函数式编程特点之一:既允许把函数本身作为参数传入另一个函数,又允许返回一个函数。
一、高阶函数
高阶函数
- 概念:高阶函数 ☞ 是 不仅可以传递变量,还可以传递函数 的函数(高阶函数又称面向对象编程)
- 区分:
① 面向函数编程:☞ 把函数传来传去,函数是第一要素
② 面向对象编程:☞ 把对象传来传去,对象是第一要素
示例:
- 知识补充 —— 传参:不仅可传值,还可传序列集合
myseq = [123, 45.67, -6.2e8] # e8:10的八次方
def mytest(num):
return num*2
mytest(10)
mytest(myseq)
[123, 45.67, -620000000.0, 123, 45.67, -620000000.0]
- 示例:高阶函数(变量可以指向函数)
myseq = [123, 45.67, -6.2e8]
def convert(func, seq): # 把函数作为参数传入
print('转换序列中的数值,要它们统一为一样的数值类型')
return [func(eachNum) for eachNum in seq]
print(convert(int, myseq)) # 效果:转为 int 类型
print(convert(float, myseq)) # 效果:转为 float 类型
print(convert(mytest, myseq)) # 效果:调用 mytest 函数,使得每个数 乘以 2
转换序列中的数值,要它们统一为一样的数值类型
[123, 45, -620000000]
转换序列中的数值,要它们统一为一样的数值类型
[123.0, 45.67, -620000000.0]
转换序列中的数值,要它们统一为一样的数值类型
[246, 91.34, -1240000000.0]
把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
Python 内建的高阶函数有:map、reduce、filter、sorted。( 内建函数:就是在 Python 中被自动加载的函数,任何时候都可使用 )
map
map 函数:会根据提供的函数对指定序列做映射
语法格式:
map(function, iterable, ...)
# 参数含义:
# function: 表示一个函数名 或者 None
# iterable: 可以是序列、支持迭代的容器或迭代器
示例:
- 高阶函数 map() 的实现 f(num)=num*2
myseq = [123, 45.67, -6.2e8]
def mytest(num):
return num*2
list(map(mytest, myseq)) # 将 map 对象转成 list 列表
# 代码描述
# 1. 定义了一个函数 mytest,返回某个数 乘以2 以后的结果;
# 2. 接着调用 map 函数将 myseq 序列中每个元素取出来,作为 mytest 的参数调用 mytest 函数;
# 3. 之后将结果转换为列表的形式显示。
[246, 91.34, -1240000000.0]
- 高阶函数 map() 的传入两个列表的使用
def f(x,y):
return x+y
list(map(f,[1,2,3,4],[10,20,30]))
[11, 22, 33]
图解 - map函数原理图:
reduce
reduce 函数:会对参数迭代器中的元素进行累积
语法格式:
reduce(function, iterable)
# 参数含义:
# function: 是一个带有【两个参数】的函数 (函数必须接收两个参数)
# iterable: 是一个迭代器对象
# 说明:
# reduce 把结果继续和序列的下一个元素做累积计算,其效果就是:
# reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
示例:
# reduce 实现 1~15的累加
from functools import reduce # 1. 在使用前需要 先导入 reduce 模块
data = list(range(1, 16))
print(data)
def my_add(a,b): # 2. 定义一个计算两个数的和的函数
return a+b
reduce(my_add, data)
# 3. ∵ 在调用 reduce 函数时传入了 my_add 函数和序列 data
# ∴ 程序会把序列 data 的每个元素取出来,和上次调用后的结果作为参数再次调用 my_add 函数,最后将结果返回。
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
120
filter
filter 函数:会对指定序列执行过滤操作
- 和 map() 类似,filter() 也接收一个函数和一个序列。
- 和 map() 不同的是:filter() 把传入的函数依次作用于每个元素,然后根据返回值是 True 还是 False 决定保留还是丢弃该元素。
语法格式:
filter(function, iterable)
# 参数含义:
# function: 可以是函数名称 或者 None
# iterable: 可以是序列、支持迭代的容器或迭代器
示例:
# 使用 filter 过滤列表,删掉奇数,只保留偶数(案例:输出 1~5 中的偶数)
data = list(range(1, 6))
def my_condition(x):
return x%2==0
print(list(filter(my_condition, data)))
[2, 4]
图解 - filter函数原理图:
sorted
sorted 函数:可以对 list 进行排序
示例:
# sorted 可以接收一个 key 函数来实现自定义的排序
sorted([1,3,6,-20,-70],key=abs) # 根据 abs 函数 取绝对值进行排序
[1, 3, 6, -20, -70]
二、匿名函数
在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数(使用 lambda 声明)更方便。
使用 lambda 声明函数的语法格式:
lambda arg1,arg2,arg3... : <表达式>
# arg1/arg2/arg3 为函数的参数,<表达式> 相当于函数体。
# 运算结果是:表达式的运算结果。
示例:使序列中每个元素都 乘以 2
- 普通方式声明函数
myseq = [123, 45.67, -6.2e8]
def mytest(num):
return num*2
list(map(mytest, myseq)) # 将 map 对象转成 list 列表
[246, 91.34, -1240000000.0]
- 使用 lambda 声明一个匿名函数
# 匿名函数实现
list(map(lambda x: x*2, myseq))
[246, 91.34, -1240000000.0]
注意:匿名函数有个限制 ☞ 只能有一个表达式,不用写 return,返回值就是该表达式的结果。
三、闭包
闭包需满足的条件:
- 存在于嵌套关系的函数中;
- 嵌套的内部函数引用了外部函数的变量;
- 嵌套的外部函数会将内部函数名作为返回值返回。
说明:
- 闭包可理解为一个封闭的包裹,这个包裹就是一个函数。
- 如果调用一个函数 A,这个函数 A 返回一个函数 B,这个返回的函数 B 就叫作 闭包。
示例:
- 闭包的方式实现两数相加
# 外部函数
def func_out(num1):
# 内部函数
def func_in(num2):
return num1+num2 # 引用外部函数的变量 num1
# 返回内部函数的名称
return func_in
f=func_out(10) # 将调用外部函数 func_out 的结果赋值给变量 f,f引用的是 func_in 函数占用的内存空间
result=f(20) # 调用了 f 函数,实际上就是 func_in 函数
print('结果:',result)
结果: 30
- 闭包的方式实现内容的打印
def log(func):
def wrapper(a, b):
func("%s和%s相约鹊桥"%(a,b))
func("%s和%s看电影"%(a,b))
func("%s和%s明年见"%(a,b))
return wrapper # 返回函数名,即:返回函数的逻辑
log(print)("牛郎", "织女")
牛郎和织女相约鹊桥
牛郎和织女看点电影
牛郎和织女明年见
程序执行过程:
四、装饰器
装饰器(decorator):本质上是一个Python 函数(装饰器是一种闭包),它可以在不改动其他函数的前提下,对函数的功能进行扩充。
装饰器的语法:
@装饰器名称
# 符号“@”放在函数或类的定义行之前
示例:
def log(func):
def wrapper():
print("约会开始了")
func()
print("明年见")
return wrapper
@log # 等价于 my_deca = log(my_deca)
def my_deca():
print("牛郎和织女看电影")
my_deca()
约会开始了
牛郎和织女看电影
明年见
程序执行过程分析:
—— 说明:本文内容基于python3.0