python 装饰器和生成器的联合使用 及他们的小细节

#装饰器是以闭包为基础
#开发场景举例 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
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值