文章目录
装饰器
开放封闭原则
1、开放:对扩展是开放的
2、封闭:对修改是封闭的
(不能修改被装饰的函数的源代码)
(不能修改被装饰的函数的调用方式)
实现装饰器知识储备
1、函数既"变量"
2、高阶函数
a.把一个函数名当做实参传给另一个函数
b.返回值中包含函数名
3、嵌套函数
高阶函数+嵌套函数 —> 装饰器
4、语法糖
@timmer ----> func = timmer(func)
python的内存回收机制
当没有变量在引用内存中的内存地址时,这个内存地址才会释放
高阶函数
a、把一个函数名当做实参传给另一个函数
# 代码一
import time
def func():
time.sleep(1)
print('in the func')
def timmer(f):
start = time.time()
f()
end = time.time()
print('the func run time is %s' %(end-start))
timmer(func)
代码一:对于装饰器来说调用方式发生了而改变
b、返回值中包含函数名
# 代码二
import time
def func():
time.sleep(1)
print('in the func')
def timmer(f):
print('新功能')
return f
func = timmer(func)
func()
代码二:利用return返回原代码的函数名的特性,先执行新代码,在执行原代码
装饰器(高阶函数+嵌套函数 —> 装饰器)
# 代码三
import time
def inner(f):
def timmer():
start = time.time()
f()
end = time.time()
print('the func run time is %s' %(end-start))
return timmer
@inner # func = inner(func)
def func():
time.sleep(1)
print('in the func')
func()
代码三:熟悉程序运行原理,熟悉闭包函数的好处。不修改原来的函数,增加新的功能。
a、被装饰的函数携带参数
# 代码四
import time
def timmer(f):
def inner(*args, **kwargs):
start = time.time()
f(*args, **kwargs)
end = time.time()
print(end - start)
return inner
@timmer
def func1():
time.sleep(1)
print('func1')
@timmer
def func2(a):
time.sleep(1)
print('func2', a)
func1()
func2(2)
b、被装饰的函数携带返回值
# 代码五
import time
def timmer(f):
def inner(*args, **kwargs):
start = time.time()
ret = f(*args, **kwargs) # 接收源代码的返回值
end = time.time()
print(end - start)
return ret # 将接收源代码返回值的变量在返回给装饰后的函数
return inner
@timmer
def func1():
time.sleep(1)
print('func1')
return '返回值func1' # 源代码携带返回值
@timmer
def func2(a):
time.sleep(1)
print('func2', a)
print(func1()) # 打印源代码中的返回值
func2(2)
c、装饰器携带参数
# 代码六
user,passwd = 'lsc','123'
def auth(auth_type):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = home(*args, **kwargs)
print("---after authenticaion ")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
return wrapper
@auth
def home():
print("welcome to home page")
return "from home"
print(home())
# 代码七
user,passwd = 'lsc','123'
def auth(auth_type):
print("auth func:",auth_type)
def outer_wrapper(func):
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = func(*args, **kwargs)
print("---after authenticaion ")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
return wrapper
return outer_wrapper
@auth(auth_type="local") # 先执行
def home():
print("welcome to home page")
return "from home"
print(home()) #wrapper()
总结:将代码六和代码七对比,发现当装饰器带参数的时候,第一个嵌套函数带入的是装饰器的参数,第二个嵌套函数带入的才是被装饰的函数,可以说是整体下移一位。
from functools import wraps
user,passwd = 'lsc','123'
def auth(auth_type):
@wraps(auth_type) # 添加这个函数,打印函数的名字依然是源代码的函数名
def wrapper(*args, **kwargs):
print("wrapper func args:", *args, **kwargs)
username = input("Username:").strip()
password = input("Password:").strip()
if user == username and passwd == password:
print("\033[32;1mUser has passed authentication\033[0m")
res = home(*args, **kwargs)
print("---after authenticaion ")
return res
else:
exit("\033[31;1mInvalid username or password\033[0m")
return wrapper
@auth
def home():
print("welcome to home page")
return "from home"
print(home.__name__)