#装饰器是以闭包为基础
#开发场景举例 1 电影买票 判断用户是否登录 如果登录后才能买票
#2 加入购物车 判断用户登录状态 如果登录才能买东西 修改密码等
以下代码实现几个小要求
1 现在有两个对象调用一个装饰器函数
2 计算函数被调用了几次
3 带参装饰器 加 带参函数 #三层def
//#现在有两个对象调用一个装饰器函数
def decorator(a):
print('装饰器参数为{}'.format(a))
parameter=a
def wrapper(func):
count=0
def inner(*args,**kwargs):
nonlocal parameter
nonlocal count
res=func(*args,**kwargs)
count+=1
print('内部 这是第{}次调用该函数'.format(count))
print('内部 第一层装饰器参数为{}'.format(parameter))
return res
return inner
return wrapper
@decorator(100) #当一个装饰器被使用后,先执行三层结构中的第一层
def func1(x,y):
print("func1执行的结果为{}".format((x+y)))
p1=func1(50,20)
p2=func1(50,30)
func1(20,59)
结果为
装饰器参数为100
func1执行的结果为70
内部 这是第1次调用该函数
内部 第一层装饰器参数为100
func1执行的结果为80
内部 这是第2次调用该函数
内部 第一层装饰器参数为100
func1执行的结果为79
内部 这是第3次调用该函数
内部 第一层装饰器参数为100
2号例子 要求如下
奥运会打靶,打一次计算一次平均值
要求: 可以无限传值 使用生成器 使用两个对象调用同一个生成器
生成器可以通过两个对象分别调用,每个对象调用一个生成器 他们的运行次数不干涉
// #日常例子,奥运会打靶,打一次计算一次平均值
#要求: 可以无限传值
def average():
sum=0
count=0
avg=0
while True:
num=yield avg #用生成器 用一次调用一次 不浪费内存
sum+=num #yield右边的avg 每次调用生成器返回yield右边的值
count+=1
avg=sum/count
avg_g=average()
avg_g.__next__() #每次用生成器时 都需要进行一次next 但是可以通过装饰器加快这个节奏
avg1=avg_g.send(10) #建立一个对象 接收avg.send 返回的值
print(avg1)
avg1=avg_g.send(5)
print(avg1)
print('---------------二号对象调用生成器---------------')
#生成器可以通过两个对象分别调用,每个对象调用一个生成器 他们的运行次数不干涉
avg_b=average()
avg_b.__next__()
avg2=avg_b.send(10)
print(avg2)
结果为
10.0
7.5
---------------二号对象调用生成器---------------
10.0
每次用生成器时 都需要进行一次next 但是可以通过装饰器加快这个节奏
下边利用装饰器 装饰器中的方法是调用__next__ 让每个生成器不再单独写__next__
这就是装饰器和生成器一起使用
//def decorator(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs) #必须这么写 否则报错 将func传给一个对象 然后对象调用__next__()
res.__next__()
return res
return wrapper
@decorator
def average():
sum=0
count=0
avg=0
while True:
num=yield avg #用生成器 用一次调用一次 不浪费内存
sum+=num #yield右边的avg 每次调用生成器返回yield右边的值
count+=1
avg=sum/count
avg_g=average()
avg1=avg_g.send(8)
print(avg1)
avg1=avg_g.send(10)
print(avg1)
avg1=avg_g.send(10)
print(avg1)
结果为
8.0
9.0
9.333333333333334
最后一个例子 是一个函数同时调用了两个装饰器 从下到上依次调用装饰器
观察代码的输出 理解代码执行顺序
//#双重装饰器
def decorate1(func):
print("装饰器1开始启动")
def wrapper(*args,**kwargs):
#执行母函数
func(*args,**kwargs)
print("1号装饰器内部函数执行")
print("装饰器1结束")
return wrapper
def decorate2(func):
print("装饰器2开始启动")
def wrapper(*args,**kwargs):
func(*args,**kwargs)
print(args)
print("2号装饰器内部函数执行")
print("装饰器2结束")
return wrapper
@decorate2
@decorate1
def func1(*args,**kwargs):
print("德玛西亚的威名是{}".format(args))
for i in args,kwargs:
print(i)
students=['lili','dema','20']
func1(students)
print("我要开始了")
结果为
装饰器1开始启动
装饰器1结束
装饰器2开始启动
装饰器2结束
德玛西亚的威名是(['lili', 'dema', '20'],)
(['lili', 'dema', '20'],)
{}
1号装饰器内部函数执行
(['lili', 'dema', '20'],)
2号装饰器内部函数执行
我要开始了
三号装饰器应用:
在类内部的函数中调用装饰器
//
def property1(func):
def wrapper(*args,**kwargs):
print('装饰器已执行')
func(*args,**kwargs)
return func(*args,**kwargs)
return wrapper
class Circle():
PI = 3.1416
def __init__(self,radius):
self.radius=radius
@property1
def perimeter(self):
return 2*self.PI*self.radius
@property1
def area(self):
return self.PI*(self.radius**2)
if __name__=='__main__':
i=Circle(5)
k= i.perimeter()
print(k)
结果为:
装饰器已执行
31.416