1.如何解决在函数执行之前和执行之后添加功能,调用函数的方式改变的问题。
不改变原有函数的调用方法:函数里面嵌套函数,并且返回嵌套函数login =desc(login)
def desc(fun): ##fun=login def add_info(): print("hello") fun() ##login() print("hi") return add_info def login(): ##print("hello") print("login") ##print("hi") login=desc(login) ##返回值是一个函数 login()


2.装饰器定义:
装饰器的实现是函数里面嵌套函数
装饰器的本质是一个函数,他可以让其他函数在不需要任何代码改动的前提下增加额外的功能
装饰器需要传递一个函数,返回值也是一个函数对象
3.装饰器的应用场景(计时器)
装饰器需求:获取每个函数的执行时间
函数执行之前计算时间
函数执行之后计算时间
【1】字符串拼接效率:“hello”+“world”
“ ”.join(['hello',"world"])
import random
import string
import time
li=[random.choice(string.ascii_letters) for i in range(100)]
def timeit(fun):
def wrapper():
start_time=time.time()
fun()
end_time=time.time()
print("运行时间:%.6f" %(end_time-start_time))
return wrapper
@timeit
def con_add():
s=' '
for i in li:
s +=(i+",")
print(s)
@timeit
def join_add():
print(",".join(li))
con_add()
join_add()


【2】检测列表生成式和map的效率的高低,n为函数传入参数:
[n*2 for i in range(10)]
map(lamdba x: x*2,range(n))
import random
import string
import time
def timeit(fun):
def wrapper(*args,**kwargs):
start_time=time.time()
fun(*args,**kwargs)
end_time=time.time()
print("运行时间:%.6f" %(end_time-start_time))
return wrapper
@timeit
def fun_list(n):
print([2*n for i in range(n)])
@timeit
def fun_map(n):
print(list(map(lambda x: x*2,range(n))))
fun_list(100)
fun_map(100)


4.装饰器函数属性变化解决方案
装饰的函数有返回值解决方法
如何保留被装饰函数的函数名和帮助文档信息
import random
import string
import time
import functools
from functools import reduce
li=[random.choice(string.ascii_letters) for i in range(100)]
def timeit(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time=time.time()
res = fun(*args,**kwargs)
end_time=time.time()
print("运行时间:%.6f" %(end_time-start_time))
return res
return wrapper
@timeit
def fun_list(n):
print([2*n for i in range(n)])
@timeit
def fun_map(n):
print(list(map(lambda x: x*2,range(n))))
fun_list(10)
fun_map(10)
print(fun_list.__name__)
print(fun_list.__doc__)


例:创建装饰器,要求:创建add_log装饰器,被装饰的函数打印日志信息;日志格式为[字符串时间]
函数名:xxx,运行时间:xxxx,运行返回值结果:xxxx
import functools
import time
import string
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
run_time=time.ctime()
fun_name=fun.__name__
start_time=time.time()
res=fun(*args,**kwargs)
end_time=time.time()
print("[%s]函数名:%s.运行时间:%.5f,运行返回值结果:%d"
%(run_time,fun_name,end_time-start_time,res)
)
return res
return wrapper
@add_log
def add(x,y):
time.sleep(0.1)
return x+y
print(add(1,2))


5.装饰器 方法2:
【1】例:需求:用户登录验证的装饰器is_login
如果用户登陆成功,执行被装饰的函数
如果用户登陆不成功,则执行登陆函数
import functools
login_users=['admin','root']
def is_login(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
if kwargs.get("name") in login_users:
res=fun(*args,**kwargs)
return res
else:
res=login()
return res
return wrapper
@is_login
def writeBlog(name):
return "编写博客"
def login():
return "登陆"
def news():
print("新闻")
print(writeBlog(name="root"))


【2】判断变量的数据类型
确保函数接受的每个参数都是整数
如果参数不是整数,打印TypeError:参数必须是整形
import functools
def required_ints(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(1,int):
print("Error:函数参数必须是整形")
break
else:
res=fun(*args,**kwargs)
return res
return wrapper
@required_ints
def add(a,b):
return a+b
@required_ints
def myMax(a,b,c,d):
return (a,b,c,d)
print(add(1,2))


6.带有多个装饰器的函数
def makebold(fun):
print("bold1")
def wrapper1(*args,**kwargs):
print("bold2")
return fun(*args,**kwargs)
return wrapper1
def makei(fun):
print("i1")
def wrapper(*args,**kwargs):
print("i2")
return fun(*args,**kwargs)
return wrapper
@makebold
@makei
def login():
return "登陆"
print(login())

注意:当有多个装饰其实,从下到上调用装饰器;
真实wrapper内容执行是从上到下执行
7.带有参数的装饰器
例1:创建装饰器,要求:创建add_log装饰器,被装饰的函数打印日志信息;日志格式为[字符串时间]
函数名:xxx,运行时间:xxxx,运行返回值结果:xxxx
import functools
import time
import string
def log(kind):
def add_log(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
start_time=time.time()
res=fun(*args,**kwargs)
end_time=time.time()
print("<%s> [%s]函数名:%s.运行时间:%.5f,运行返回值结果:%d"
%(kind,time.ctime(),fun.__name__,end_time-start_time,res)
)
return res
return wrapper
return add_log
@log("debug")
def add(x,y):
time.sleep(0.1)
return x+y
print(add(1,2))


例2:编写装饰器required_types,条件如下:
当装饰器为@required_types(int,float)确保函数接受到的参数都是int类型或者float类型
当装饰器为@required_types(list)确保函数接受到的参数都是list类型
当装饰器为@required_types(str,int)确保函数接受到的参数都是int类型或者str类型
如果不满足条件,打印参数必须为xxxx类型
import functools
def required_types(*kinds):
def required(fun):
@functools.wraps(fun)
def wrapper(*args,**kwargs):
for i in args:
if not isinstance(i,kinds):
print("Error:函数参数必须是整形",kinds)
break
else:
res=fun(*args,**kwargs)
return res
return wrapper
return required
@required_types(int,float)
def add(a,b):
return a+b
@required_types(int)
def myMax(a,b,c,d):
return (a,b,c,d)
print(add(1,2.0))


本文详细介绍了Python中装饰器的概念、实现方式及其应用场景,包括计时器、参数类型检查等实用案例。
1792

被折叠的 条评论
为什么被折叠?



