闭包和装饰器
闭包
- 必须有一个内嵌函数
- 内嵌函数必须引用外部函数中的变量
- 外部函数的返回值必须是内嵌函数
注:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量。
def Outer():
count = 0
def Inner():
nonlocal count
count += 1
print("执行了Inner函数, count =", count)
return Inner
# Outer() -> Inner
#f = Outer() -> f = Inner
#f() -> Inner
#Outer()() -> Inner
Outer()() 执行了Inner函数, count = 1
Outer()() 执行了Inner函数, count = 1
Outer()() 执行了Inner函数, count = 1
f = Outer()
f() 执行了Inner函数, count = 1
f() 执行了Inner函数, count = 2
f() 执行了Inner函数, count = 3
装饰器
在不影响被装饰函数原本功能的基础上,添加其他功能(装饰器)
# def ABC(name): # 被装饰函数
# print(f"{name}爬虫开始执行....")
# time.sleep(3)
# print(f"{name}爬虫结束执行....")
被装饰函数和装饰器都不带参数
def 装饰器名字(被装饰函数):
def inner():
装饰功能1
执行被装饰函数
装饰功能2
return inner
# 记录代码运行时间
import time
start = time.time()
for i in range(100000):
pass
end = time.time()
print(end - start)
---------------------------------
def ABC(): # 被装饰函数
print("爬虫开始执行....")
time.sleep(3)
print("爬虫结束执行....")
# 记录时间装饰器
def recordTime(f): # 装饰器
def inner():
start = time.time() # 装饰器功能1
f() #被装饰函数
end = time.time() # 装饰器功能2
print(f"函数执行了{end-start}秒")
return inner
# f -> ABC
# recordTime(ABC) -> inner
# recordTime(ABC)() -> inner()
recordTime(ABC)()
被装饰函数带参数,装饰器不带参数
def ABC(name): # 被装饰函数
print(f"{name}爬虫开始执行....")
time.sleep(3)
print(f"{name}爬虫结束执行....")
def DEF(name, age): # 被装饰函数
print(f"{name}爬虫开始执行....", age)
time.sleep(3)
print(f"{name}爬虫结束执行....", age)
def recordTime(f): # 装饰器
def inner(*args, **kwargs):
start = time.time() # 装饰器功能1
f(*args, **kwargs) #被装饰函数
end = time.time() # 装饰器功能2
print(f"函数执行了{end-start}秒")
return inner
recordTime(ABC)("Tom")
recordTime(DEF)("Tom", 18)
被装饰函数和装饰器都带参数
def 装饰器名字(被装饰函数):
def outer(被装饰函数):
def inner(*args, **kwargs):
装饰功能1
执行被装饰函数(*args, **kwargs)
装饰功能2
return inner
return outer
------------------------------------
def ABC(name): # 被装饰函数
print(f"{name}爬虫开始执行....")
time.sleep(3)
print(f"{name}爬虫结束执行....")
def recordTime(name): # 装饰器
def outer(f):
def inner(*args, **kwargs):
start = time.time() # 装饰器功能1
f(*args, **kwargs) #被装饰函数
end = time.time() # 装饰器功能2
print(f"装饰器{name}, 函数执行了{end-start}秒")
return inner
return outer
# recordTime("装饰器A") -> outer
# recordTime("装饰器A")(ABC) ->inner
# recordTime("装饰器A")(ABC)("Tom") -> inner("Tom")
recordTime("装饰器A")(ABC)("Tom")
装饰器的调用方法
第一种:
装饰器(被装饰函数)()
第二种:
在被装饰函数上面加@ 如果装饰器带参数则@装饰器名(装饰器参数) 如果装饰器不带参数则@装饰器名
多个装饰器嵌套
def decorator_A(f): # 装饰器A
print("开始执行装饰器A")
def inner(*args, **kwargs):
print("执行装饰器A功能1")
f(*args, **kwargs) # 被装饰函数
print("执行装饰器A功能2")
return inner
def decorator_B(f): # 装饰器B
print("开始执行装饰器B")
def inner(*args, **kwargs):
print("执行装饰器B功能1")
f(*args, **kwargs) # 被装饰函数
print("执行装饰器B功能2")
return inner
@decorator_A
@decorator_B
def Test():
print("执行了被装饰函数Test")
Test()