装饰器 闭包 如果一个内嵌函数,对外面的函数内的变量进行引用,那么内嵌这个函数是闭包 三个条件: 1.内外函数嵌套 2.把内函数作为参数传入外函数 3.外函数返回内函数 被装饰过的函数已经是另外的函数,函数名或者函数属性都会发生变化,副作用 wraps包作用消除这种副作用 保留原函数属性
进行加法运算 值:26 注:装饰器流程
def wai(f): # (2)触发装饰器函数
def nei(*b): # (4)加*的变量 用于储存未命名变量
print(*b) # (5) 5 6 6 9
return f(*b) # (6)把内层数据 通过f() 传给wai()函数
return nei # (3)返回给内函数
@wai # (1)函数执行前必须先走一遍装饰器 (7)此时装饰器已经走了一遍
def func(*b):
print('进行加法运算') # (8)此时才进入func()函数
return sum(b) # (9)返回结果
print(func(5, 6, 6, 9)) # (0)调用func() 函数
普通装饰器
def my_decorator(func): # 1.把wrapper()函数作为参数func 传入外函数
@wraps(func)
def wrapper():
start_time = time.time()
print('1')
func() # 2.内部函数必须引用外部函数func变量
print(time.time() - start_time) # 最后执行,多用于计算时间
return wrapper # 3.外函数返回内函数
@my_decorator
def test():
time.sleep(2)
if __name__ == '__main__':
test() # 2.0169763565063477
print(test.__name__) # 不定义@wraps(func) 咋打印函数名wrapper
嵌套装饰器 可以传参数的装饰器
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for i in range(n):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet(name):
print(f"Hello, {name}!")
greet("Fox")
多层装饰器执行顺序
装饰器采用内外函数嵌套,功能在内函数体,所以执行顺序是从上到下
import time
from functools import wraps
def decorator1(func):
print('1外函数')
@wraps(func)
def wrapper():
print('装饰器1(内函数)')
func()
print('装饰器1---(内函数)')
return wrapper
def decorator2(func):
print('2外函数')
@wraps(func)
def wrapper():
print('装饰器2(内函数)')
func()
print('装饰器2---(内函数)')
return wrapper
@decorator2
@decorator1
def test():
print('原函数')
if __name__ == '__main__':
test()
<p><a>人生苦短,我用python</a></p>
def wai(f):
def nei():
return "<a>" + f() + "</a>"
return nei
def wai2(f):
def nei2():
return "<p>" + f() + "</p>"
return nei2
@wai2 # 后执行,加在外层
@wai # 先执行
def func():
return "人生苦短,我用python"
print(func())