什么是装饰器?
官方解释:
装饰器是用来管理和调用函数和类的一个可调用对象,也就是说分为函数装饰器和类装饰器;
但是看完之后,我并不能明白装饰器的含义!!所以我在网上进行了查找,觉得下面的这个解释很通俗,引用于
https://m.php.cn/article/424884.html
装饰器就是对被装饰的对象(函数、类)进行重构的,其可以在不改变原来对象的情况下调用对象时执行重构后的行为。
这里也引用作者得python代码:
def decorator(f):
def wrapper(x,y):
return x+y
return wrapper
@decorator
def func(x,y):
return 1
func(3,4)
我把这句话分为了三层意思进行理解:
1、装饰器:我们的装饰函数;
2、被装饰对象:引用装饰器的函数或类(类的概念现在还没有学到);
3、返回得可调用对象:装饰器得内嵌函数;
4、重构:(对对象进行重构)
原文作者有提到这样一句话,讲的是****装饰器本身接受被装饰的对象,装饰器返回的可调用对象接受被装饰对象的所有参数。
在上面那一段代码中,
装饰器是: decorator
返回的可调用对象是: wrapper
被装饰的对象是 :func
当调用func(3,4)的时候发生了什么?
此时:返回的可调用对象(wrapper)给了func,你也可以理解为现在的func的代码是
def func(x,y)
return x+y
装饰器的练习
timeit 是一个函数,它接受一个参数,这个参数必须是函数(或者说可调用对象或者说是被修饰的函数),并且 timeit 的返回结果一定是一个函数。
带参装饰器
参数分为形式参和实参,带参装饰器其实就是说我们的装饰器中的函数是带有参数的,如果我们在调用函数的时候不手动赋值,那么参数就是使用的默认值,如果手动赋值,那么参数的结果就是我们自己的手动赋值;
引入菜鸟教程的例子:
地址:
https://www.runoob.com/w3cnote/python-func-decorators.html
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
myfunc1()
# Output: myfunc1 was called
# 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串
@logit(logfile='func2.log')
def myfunc2():
pass
myfunc2()
# Output: myfunc2 was called
# 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串
保留被装饰函数的函数名字和帮助文档信息在装
饰器函数的下面(闭合函数的上面加:@functools.wraps(fun))
import functools
import random
import string
import time
li = [random.choice(string.ascii_letters) for i in range(100)]
print(time.time()) #打印处自1970年到现在一共多少秒
def timeit(fun):
# @functools.wraps(fun)
def wrapper(*args,**kwargs): #接收可变参数 和 关键字参数
"""这是一个装饰器timeit"""
# 在函数执行之前
start_time = time.time()
# 执行函数
res = fun(*args,**kwargs)
# 在函数执行之后
end_time = time.time()
print('运行时间为:%.6f' %(end_time - start_time))
return res
return wrapper
@timeit
def con_add():
"""这是一个con_add"""
s = ''
for i in li:
s +=i
print(s)
con_add()
print(con_add.__name__)
print(con_add.__doc__)
如果不加@functools.wraps(fun),则显示的是装饰器的信息
多个装饰器
多个装饰器装饰函数 从上到下去执行的
def decorator_a(fun):
def inner_a(*args,**kwargs): #接收可变参数和关键字参数
print('Get in inner_a')
fun(*args,**kwargs)
return inner_a
def decorator_b(fun):
def inner_b(*args,**kwargs):
print('Get in inner_b')
fun(*args,**kwargs)
return inner_b
#多个装饰器装饰函数 从上到下去执行的
@decorator_a
@decorator_b
def f(x):
print('Gat in f')
f(1)
装饰器的应用
多个装饰器的应用场景
会采用多个装饰器先验证是否登陆成功 再验证权限是否足够
import inspect
login_session = ['root','admin','redhat']
import functools
def is_login(fun):
@functools.wraps(fun)
def warapper(*args,**kwargs):#('root',)如果有多个可变参数,args会存成元组
print(args)
if args[0] in login_session:
temp = fun(*args,**kwargs)
return temp
else:
print()
print('Error:%s 没有登陆成功' %(args[0]))
return warapper
def is_admin(fun):
@functools.wraps(fun)
#inspect_res 会返回一个字典
# key:形参 value:对应的实参
def wrapper(*args,**kwargs):
inspect_res = inspect.getcallargs(fun,*args,**kwargs)
print('inspect的返回值是:%s' %(inspect_res))
if inspect_res.get('name') == 'root':
temp = fun(*args,**kwargs)
return temp
else:
print('not root user,no permisson add user')
return wrapper
@is_login
@is_admin
def adduser(name):
print('add_user')
adduser('refhat')