1.介绍
装饰器本质是函数(闭包函数)
能够在不变动原函数的情况下进行,给函数增加其它的功能
2.函数装饰器
def demo(function):
def inner():
print('装饰器启用')
function()
print('结束')
return 1
return inner
@demo
def data():
print('data函数')
a = data()
print(a)
# 1.此时返回值是装饰器demo的返回值
# 2.触发demo装饰器,在其闭包中进行调用函数 --- 增加操作空间
运行结果
分析
返回值问题
def demo(function):
def inner():
print('装饰器启用')
num = function()
print('结束')
return num
return inner
@demo
def data():
print('data函数')
return 1
a = data()
print(a)
3. python自带的核心装饰器
通常在类方法中使用
@property # 像属性一样调用 --- 无法直接方法传参
@staticmethod # 让方法成为 静态方法(无self,cls)
@classmethod # 让方法成为 类方法
class Demo(object):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
areas = self.length * self.width
return areas
@property # 像属性一样调用 --- 无法直接方法传参
def data1(self):
return '装饰器property --- data1'
@staticmethod # 让方法成为 静态方法(无self,cls)
def data2():
return '装饰器staticmethod ---- data2'
@classmethod # 让方法成为 类方法
def data3(cls):
return '装饰器classmethod --- data3'
dms = Demo(12, 23)
print(dms.area()) # 276
print(dms.data1) # 装饰器property --- data1
print(dms.data2()) # 装饰器staticmethod ---- data2
print(dms.data3()) # 装饰器classmethod --- data3
4.类装饰器
class DemoClass(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('类装饰器 ---- 调用')
self.func()
print('类装饰器 ---- 结束')
return 1
@DemoClass
def play():
print('play函数')
print(play())
返回值问题
class DemoClass(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('类装饰器 ---- 调用')
data = self.func()
print('类装饰器 ---- 结束')
return data
@DemoClass
def play():
print('play函数')
return 'play返回值'
print(play())
5.装饰器传参问题
在装饰器中调用方法时,加上不定长参数即可解决
如下:
函数
def demo(function):
def inner(*args):
print('装饰器启用')
function(*args)
print('结束')
return '返回值'
return inner
@demo
def data(a):
print(a)
print('data函数')
a = data(123)
print(a)
类
class DemoClass(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('类装饰器 ---- 调用')
self.func(*args)
print('类装饰器 ---- 结束')
return 1
# __call__:魔法方法之一,使得类实例对象可以像调用普通函数那样,以“对象名()”的形式使用。
@DemoClass
def play(a):
print(a)
print('play函数')
print(play(12345))
6.装饰器案例
统计函数运行时间的装饰器
import time
def run_time(function):
def new_fun(*args, **kwargs):
to = time.time() # 起始时间
back = function(*args, **kwargs)
end = time.time() # 结束时间
print(f'函数执行时间为:{end-to}')
return back
return new_fun
@run_time
def for_demo(num=10):
data = 0
for i in range(num):
data += i
return data
if __name__ == '__main__':
data1 = for_demo(10000000)
print(data1)