如果一个函数的参数是函数类型,那么这个被传入的、后又被调用的函数就称为回调函数(callback function)。
函数中调用函数,如果调用的是他本身叫递归,如果调用的是别的函数叫普通调用,如果调借用参数调用别的函数叫回调
def get_min(a,b,fun): # 来 传来的函数func; 回:我把参数回传给你-func
result=a if a<b else b
fun(a,b,result)
def print_min(a,b,c):
print(f'compare {a}和{b},min is {c}')
if __name__ == '__main__':
get_min(3,2,print_min)
闭包就是能够读取外部函数内的变量的函数。
import logging
def logger(fun):
def log_fun(*args):
logging.basicConfig(filename='demo.log',level=logging.INFO)
logging.info(f'{fun.__name__}is running,args are {args}')
# 返回函数,不加括号
return log_fun # 把log_func函数的引用,传给logger的调用者
def f1(a,b):
pass
def f2(x,y):
pass
f1_logger=logger(f1)
f2_logger=logger(f2)
f1_logger(1,2)
f2_logger(3,4)
-------输出结果--------
INFO:root:f1is running,args are (1, 2)
INFO:root:f2is running,args are (3, 4)
以上例子中的log_fun函数就是个闭包函数,当调用logger时,执行到return log_fun时再执行log_fun函数。
闭包函数的作用:
作用1:闭包是将外层函数内的局部变量和外层函数的外部连接起来的一座桥梁。(下一部分讲解)
作用2:将外层函数的变量持久地保存在内存中。(下一部分讲解)
1)可以读取函数内部的变量
def tag_test(name):
def set_tag(content):
return f"<{name}>{content}<{name}>"
return set_tag
a = tag_test('a')
print(a("hello"))
-------输出结果--------
<a>hello<a>
我们设计一个给content加tag的功能,但是具体的tag_name是什么样子的要根据实际需求来定,对外部调用的接口已经确定,就是set_tag(content)。如果按照面向接口方式实现,我们会先把add_tag写成接口,指定其参数和返回类型,然后分别去实现a和b的add_tag。
但是在闭包的概念中,set_tag就是一个函数,它需要name和content两个参数,只不过name这个参数是打包带走的。所以一开始时就可以告诉我怎么打包,然后带走就行。
2)让这些变量的值始终保持在内存中
一般来说,函数内部的局部变量在函数运行完以后,就会被Python的垃圾回收机制从内存中清除掉。如果我们希望这个局部变量能够长久的保存在内存中,那么就可以用闭包来实现这个功能
def move(pos=[0, 0]):
def go(direct, step):
x1 = pos[0] + direct[0] * step
y1 = pos[1] + direct[1] * step
pos[0], pos[1] = x1, y1
return pos
return go
p1 = move()
print(p1([0,1],5))
print(p1([1,2],10))
-------输出结果--------
[0, 5]
[10, 25]
可以看出,第一次是沿Y轴前进了5来到[0, 5],第二次是在第一次的位置基础上来到 [10, 25],证明了pos的变量一直保存在内存中,并没有在move函数调用后就清除。