在Python中,装饰器是一种特殊的语法,用于修改或增强函数的功能。装饰器是Python的高级特性之一,它允许我们通过在不修改原函数代码的情况下,添加额外的功能或行为。
装饰器是一个函数,它接受一个函数作为参数,并返回一个新的函数。装饰器函数通常使用
@
符号放在要修饰的函数定义之前
python中的装饰器(decorator)一般采用语法糖的形式,是一种语法格式。比如:@classmethod,@staticmethod,@property,@wraps(),等都是python中的装饰器。
#装饰器: 是一种程序设计模式,主要用于给函数或者类添加一些额外的功能
# 又不希望通过继承或者修改源代码的方式去实现,那就使用装饰器
# 装饰器:不改变函数或类或者源代码的基础上,添加额外功能。
# 装饰器的本质就是闭包,它需要把一个callable对象(能够打括号调用的对象)作为参数转递进来。
闭包:需要满足三个条件
函数体内的局部变量,一般情况下,调用的时候生成,结束的使用释放
在闭包的条件下,局部变量不会随着调用的结束而释放
变量生命周期
局部变量 -- 函数的调用生成,函数调用完成释放
def func1():
print("i am func1")
def outer():
x = 30
func1()
print(f"x is {x}")
outer()
print(x)
def outer(x):
a = 200
def inner():
print(x+a)
return inner
d = outer(100)
#此时,d就是内函数,如果不调用d,就不会有输出
# d()
# 我们需要调用内函数才可以看到调用结果。
看一段代码执行时间:
定义func1函数
def func1():
time.sleep(1)
print("i am func1")
在函数前后查看时间。
func1()
# 时间戳
start = time.time()
f = func1()
end = time.time()
print(f"执行函数花了{end-start}s")
使用装饰器查看时间
定义装饰器
def runtime(func):
def inner(*args,**kwargs): # *args, **kwargs 让装饰器更加通用。
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print(f"函数执行花了{end-start}s")
print(f"执行了{func.__name__}函数")
return result # inner 函数返回原函数的返回值。
return inner
定义函数
@runtime
def func2(a,b):
time.sleep(2)
print("i am func2")
return a+b
func2(1,2)
注意:
练习:
添加额外功能
统计运行时间
权限控制
日志记录
执行了什么函数 -- 写入日志,记录INFO 等级 ,写到文件和屏幕
计时功能装饰器
import functools
from logset import logger
def log(func):
def inner_log(*args, **kwargs):
logger.info(f"开始执行{func.__name__}函数")
result = func(*args, **kwargs)
logger.info(f"{func.__name__}函数,执行结束!")
return result
return inner_log
def runtime(func):
@functools.wraps(func)
def inner(*args,**kwargs):
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print(f"函数执行花了{end-start}s")
return result
return inner
@log # test_func1 = log ( runtime( test_func1() ) )
@runtime
def test_func1():
time.sleep(1)
print("this is func1")
test_func1()
自身不转入参数的装饰器,使用两层函数定义
自身转入参数的装饰器,使用三层函数定义
import time
user = {"root":"123456","admin":"admin123"}
def deco(username,passwd):
def runtime(func):
def inner(*args,**kwargs):
if username in user and user[username] == passwd:
if username == "root":
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print(f"{func.__name__}执行花了{end-start}s")
return result
else:
print("用户名密码不正确")
else:
print(f"用户:{username}没有权限")
return inner
return runtime
@deco(username="r",passwd="123456")
def add(a,b):
time.sleep(1)
return a+b
add(1,2)
import time
class A():
def __init__(self,func):
self.func = func
def __call__(self, *args, **kwargs):
start = time.time()
result = self.func()
end = time.time()
print(f"{self.func.__name__}函数执行花了{end - start}s")
return result
@A # func1 = A(func1) 这是实例化
def func1():
time.sleep(1)
print("i am func1")
func1()
带参数的装饰器,用类实现
user = {"root":"123456","admin":"admin123"}
class A:
def __init__(self,username,passwd):
self.username = username
self.passwd = passwd
def __call__(self, func):
def inner(*args, **kwargs):
if self.username in user and user[self.username] == self.passwd:
if self.username == "root":
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__}执行花了{end - start}s")
return result
else:
print("用户名密码不正确")
else:
print(f"用户:{self.username}没有权限")
return inner
@A(username = "root",passwd="123456") # a = A(username = "root"),func1 = a(func1) 这是实例化
def func1():
time.sleep(1)
print("i am func1")
func1()