python基础之—函数式编程
文章目录
一,函数式编程
1、函数作为参数
- 将核心逻辑传入方法体,使该方法的适用性更广。
#高级函数
#函数也是一种数据
def foo(x):
return 1
print(type(foo))
#回调参数 callback
#函数的参数,实际上是两个:形参和实参
#总结:函数也可以作为实参传入参数列表中
<class 'function'>
回调函数
#回调函数
#把一个函数传入另一个函数,传入的函数就是回调函数
def add(x,y):
return x+y
def sub(x,y):
return x-y
def mul(x,y):
return x*y
def div(x,y):
return x/y
x=100
y=200
print(add(x,y))
#工具函数
def calc(x,y,func):
return func(x,y)
calc(x,y,add)#传入的add就是回调函数
#回调函数怎么体现回调
# 遍历:把一个数据容器中的数据全部取出来使用
# 设计一个工具函数:遍历列表中所有的元素,找出奇数拿出来使用,但是这个工具自己并不使用
#而是交给业务函数使用 这里的业务函数想干啥就干啥,这个业务函数就是回调函数
def find_odd(list,fn):
for i in list:
if i%2==1:
fn(i)
x=[1,2,3,4,5,6,7,8,9,10]
def fn(i):
print(i)
find_odd(x,fn)
300
1
3
5
7
9
2,函数作为返回值
我们可以通过闭包思想完成这一特性。
闭包是指引用了此函数外部嵌套函数的变量的函数,并把该函数作为返回值,是一种思想。
2.1 闭包定义
闭包必须满足以下三个条件:
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中变量
- 外部函数返回值必须是内嵌函数
2.2 闭包优缺点
优点
- 逻辑连续,当闭包作为另一个函数调用参数时,避免脱离当前逻辑而单独编写额外逻辑。
- 方便调用上下文的局部变量。
- 加强封装性,是第2点的延伸,可以达到对变量的保护作用。
缺点
引用在,空间不灭:闭包使得函数中的变量保存在内存中,内存消耗很大
2.3闭包案例面试分析
def fun(n=None,o=None):
print(o)
return {"fun":lambda m:fun(m,n)}
a=fun(0)
a["fun"](1)
a["fun"](2)
a["fun"](3)
b = fun(0)["fun"](1)["fun"](2)["fun"](3)
c = fun(0)["fun"](1)
c["fun"](2)
c["fun"](3)
运行
None
0
0
0
None
0
1
2
None
0
1
1
自己分析
def fun(n=None,o=None):
print(o)
return {"fun":lambda m:fun(m,n)}
#定义了一个fun函数,包含两个参数,n和o,然后返回一个字典,
#字典里面有两个个键值对,第一个键值对是"fun",第二个键值对是lambda m:fun(m,n)
a=fun(0) #首先调用fun函数,传入0,得到n=0,o=None,所以输出、None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
a["fun"](1)#调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0
a["fun"](2)#调用"fun"字典,传入2,得到lambda 2:fun(2,0),然后回调得到fun(2,0)
#输出0
a["fun"](3)#调用"fun"字典,传入3,得到lambda 3:fun(3,0),然后回调得到fun(3,0)
#输出0
b = fun(0)["fun"](1)["fun"](2)["fun"](3)
#首先调用fun函数,传入0,得到n=0,o=None,所以输出、None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
#然后调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0,然后lambda 1:fun(m,1)
#然后调用"fun"字典,传入2,得到lambda 2:fun(2,1),然后回调得到fun(2,1)
#输出1,然后lambda 2:fun(m,2)
#然后调用"fun"字典,传入3,得到lambda 3:fun(3,2),然后回调得到fun(3,2)
#输出2,然后lambda 3:fun(m,3)
c = fun(0)["fun"](1)
#首先调用fun函数,传入0,得到n=0,o=None,所以输出None
#返回一个字典,然后调用字典里面的"fun"键对应的值,
#也就是lambda m:fun(m,0),然后下一步
#然后调用"fun"字典,传入1,得到lambda 1:fun(1,0),然后回调得到fun(1,0)
#输出0,然后lambda 1:fun(m,1)
c["fun"](2)
#然后调用"fun"字典,传入2,得到lambda 2:fun(2,1),然后回调得到fun(2,1)
#输出1,然后lambda 2:fun(m,1)
c["fun"](3)
#然后调用"fun"字典,传入3,得到lambda 3:fun(3,1),然后回调得到fun(3,1)
#输出1,然后lambda 3:fun(m,1)
伪代码
"""
global-->[
标识符->fun是一个函数 也就是代码 它不运行的时候 就当做一个代码片段看待(文字)
fun->def fun(n=None,o=None):
print(o)
return {"fun":lambda m:fun(m,n)}
标识符a-是fun(0)的返回值
a=fun(0)-->[
标识符n=0
标识符o=None
print(o)==>打印None
return {"fun":lambda m:fun(m,n)}
O1>>>a["fun"](1)-->[
标识符m=1
return O2>>>fun(m,n)==fun(1,0)
]
Q1>>>a["fun"](2)-->[
标识符m=2
return fun(m,n)== W1>>fun(2,0)
]
R1>>>a["fun"](3)-->[
标识符m=3
return fun(m,n)==T1>>>fun(3,0)
]
]
O1>>>a["fun"](1)
O2>>>fun(1,0)-->[
标识符n=1
标识符o=0
print(o)==>打印0
return {"fun":lambda m:fun(m,n)}
]
Q1>>>a["fun"](2)
W1>>>fun(2,0)-->[
标识符n=2
标识符o=0
print(o)==>打印0
return {"fun":lambda m:fun(m,n)}
]
R1>>>a["fun"](3)
T1>>>fun(3,0)-->[
标识符n=3
标识符o=0
print(o)==>打印0
return {"fun":lambda m:fun(m,n)}
]
b = fun(0)["fun"](1)["fun"](2)["fun"](3)
标识符b=
fun(0)-->[
标识符n=0
标识符o=None
print(o)==>打印None
return {"fun":lambda m:fun(m,n)}
fun(0)["fun"](1)-->[
标识符m=1
return T1>>>fun(1,0)
]
]
T1>>>fun(0)["fun"](1)>>>fun(1,0)-->[
标识符n=1
标识符o=0
print(o)==>打印0
return {"fun":lambda m:fun(m,n)}
fun(0)["fun"](1)["fun"](2)-->[
标识符m=2
return fun(m,n)==fun(2,1)
]
]
fun(0)["fun"](1)["fun"](2)-->fun(2,1)-->[
标识符n=2
标识符o=1
print(o)==>打印1
return {"fun":lambda m:fun(m,n)}
fun(0)["fun"](1)["fun"](2)["fun"](3)-->[
标识符m=3
return fun(m,n)==fun(3,2)
]
]
fun(0)["fun"](1)["fun"](2)["fun"](3)-->fun(3,2)-->[
标识符n=3
标识符o=2
print(o)==>打印2
return 全局变量b的结果==>{"fun":lambda m:fun(m,n)}
]
c = fun(0)["fun"](1)
c["fun"](2)
c["fun"](3)
c变量-->
fun(0)-->[
标识符n=0
标识符o=None
print(o)==>打印None
return {"fun":lambda m:fun(m,n)}
fun(0)["fun"](1)-->[
标识符m=1
return fun(m,n)==fun(1,0)
]
]
c-->fun(0)["fun"](1)-->fun(1,0)-->[
标识符n=1
标识符o=0
print(o)==>打印0
return {"fun":lambda m:fun(m,n)}
c["fun"](2)-->[
标识符m=2
return fun(m,n)==fun(2,1)
]
c["fun"](3)-->[
标识符m=3
return fun(m,n)==fun(3,1)
]
]
c["fun"](2)-->fun(2,1)-->[
标识符n=2
标识符o=1
print(o)==>打印1
rerurn {"fun":lambda m:fun(m,n)}
]
c["fun"](3)-->fun(3,1)-->[
标识符n=3
标识符o=1
print(o)==>打印1
rerurn {"fun":lambda m:fun(m,n)}
]
]
"""
简易分析a
简易分析b
简易分析c
3,装饰器
装饰器是Python对闭包思想的具体语法实现,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
- 函数的装饰器的本质就是回调函数和闭包的结合
- 装饰器本身是一个函数 它把被装饰的函数作为参数传入 然后把调用封装到内部的闭包中 返回值那个闭包
- 未来调用被装饰器装饰过的函数 相当于在调用那个闭包
- 日志记录:可以使用装饰器来记录函数的输入、输出或执行时间。
- 认证和授权:装饰器可以用于检查用户是否有权限执行特定操作。
- 缓存:装饰器可以缓存函数的结果,从而提高执行效率。
- 参数验证:可以使用装饰器来验证函数的输入参数是否符合预期。
- 代码注入:装饰器可以在函数的执行前后注入额外的代码。
3.1基本装饰器
#装饰器
def decorator1(fun):
def wrapper(*args,**kwargs):
print("wrapper")
return fun(*args,**kwargs)
print("继续装饰")
return wrapper
@decorator1
def fn():
print("业务打印")
fn()
@decorator1
def fn3():
print("fn3-66666")
fn3()
业务打印
wrapper
fn3-66666
在这里插入代码片
3.2带参装饰器
# 带参数的装饰器
def decorator2(num):
def decorator(cb):
def block():
print("装饰函数的代码")
for _ in range(num):
cb()
return block
return decorator
@decorator2(2)
def fn():
print("hello")
fn()#看起来是在调用fn 其实是在调用block
@decorator2(5)
def fm():
print("world")
fm()
fm()
- 案例 日志打印装饰器
#日志打印装饰器
def log(fun):
def wrapper(*args,**kwargs):
print("开始打印日志")
fun(*args,**kwargs)
print("结束打印日志")
return wrapper
def diaoyong(a,b):
print(a*b)
diaoyong(1,2)
2
- 传参
def decorator2(num):
def decorator(cb):
def block(a,b,c):
print("装饰函数的代码",a,b,c)
for _ in range(num):
cb()#cb就是被装饰的函数 必须具有相同的参数量
return block
return decorator
@decorator2(2)
def fn():
print("hello")
fn(10,20,30)#看起来是在调用fn 其实是在调用block
@decorator2(2)
def fm():
print("world")
装饰函数的代码 10 20 30
hello
hello
3.3装饰器链
# 装饰器链
def decorator1(cb):
def block():
print("block1")
cb()
return block
def decorator2(cb):
def block():
print("block2")
cb()
return block
@decorator1
@decorator2
def f3():
print("f3")
f3()#执行decorator1装饰器的闭包 这个闭包中 有decorator2装饰器的闭包 中有f3函数
block1
block2
f3