闭包
使用场景:默认的,函数调用完成会后,销毁函数内部定义的变量,但有时候需要保存函数内的变量,再该变量的基础上进行操作
定义:在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数的引用,把这个使用外部函数变量的内部函数称为闭包。
(内函数的引用+外部函数的环境)
使用闭包时,外部函数的变量没有及时释放,会消耗内存。
闭包的构成条件:
- 函数嵌套
- 内部函数使用了外部函数的变量(参数等)
- 外部函数返回内部函数的引用 (引用!不是调用!)、
def outer():
a = 10
def inner():
b = a + 1
print(b)
return inner
res = outer()
print(res)
print(id(res))
print(type(res))
res()
<function outer.<locals>.inner at 0x000001BFF385F158>
1923936022872
<class 'function'>
11
闭包的使用
通过对象实现对话
class Person(object):
def __init__(self, name):
self.name = name
def say(self, msg):
print(self.name + 'Says: ' + msg)
tom = Person('tom')
jack = Person('jack')
tom.say('hi')
jack.say('what are u doing')
tom.say('watching tv')
通过函数闭包的形式实现
def Person(name):
def Say(msg):
print(name + ' said:' + msg)
return Say
tom = Person('tom')
jack = Person('jack')
tom('hi')
jack('hello')
tom('bye')
↑ 闭包比类更加轻量,但是闭包并不能完全继承类。类有独有的继承的特性。
内函数修改外函数变量
需要通过nonlocal声明后使用
def outer():
n = 1
def inner():
nonlocal n
n = n + 10
print(n)
print(n)
return inner
func = outer()
func()
装饰器
给已有函数增加额外功能的函数,本质上是一个闭包函数
特点:
- 不修改原有函数代码
- 不修改已有函数调用方式
- 给已有函数增加额外功能
获取函数执行时间:
def show():
start = time.time()
for i in range(200):
time.sleep(0.01)
end = time.time()
print(f'it cose {end-start} seconds')
show()
it cose 3.175504446029663 seconds
方法二
def show():
for i in range(200):
time.sleep(0.01)
def count_time(func):
start = time.time()
func()
end = time.time()
print(f'it cose {end - start} seconds')
count_time(show)
方法三
def show():
for i in range(200):
time.sleep(0.01)
def count_time(func):
def inner():
start = time.time()
func()
end = time.time()
print(f'it cost {end - start} seconds')
return inner
# 装饰函数的原理 ----> show == inner
show = count_time(show)
show()
语法糖写法:
@count_time
def show():
for i in range(200):
time.sleep(0.01)
不同类型的装饰器在装饰函数的时候,需要根据被装饰的函数定义的格式适当接收参数和返回值,所以闭包中的内函数要相应接收参数和返回值。
无参数和返回值
def outer1(fun):
def inner1():
print('inner func')
fun()
return inner1
@outer1
def show1():
print('show1')
show1()
有参数无返回值
def outer2(fun):
def inner2(msg):
print('inner func')
fun(msg)
return inner2
@outer2
def show2(msg):
print(msg)
show2('hi')
无参数有返回值
def outer3(fun):
def inner3():
print('inner func')
res = fun()
return res
return inner3
@outer3
def show3():
return 'hi show3'
print(show3())
有参数有返回值
def outer4(fun):
def inner4(msg):
print('inner func')
res = fun(msg)
return res
return inner4
@outer4
def show4(msg):
return 'hi ' + msg
print(show4('you'))
不定参数
def outer(func):
def inner(*args, **kwargs):
res = func(*args, **kwargs)
return res
return inner
多个装饰器使用
——————睡觉了 周末再看吧