• 装饰器进阶


    1.装饰器有参数(方便控制是否装饰)

    import time
    FLAG=False   #在装饰器中传一个参数,控制是否加上装饰
    def timeer_out(flag):
        def time2(f):  # 传入的实际上是func1函数的内存地址
            def inner(*args, **kwargs):
                if flag==True:
                    startx = time.time()
                    ret = f(*args, **kwargs)
                    endx = time.time()
                    print(endx - startx)
                    return ret
                else:
                    ret = f(*args, **kwargs)
                    return ret
            return inner
        return time2
    
    @timeer_out(FLAG)            #time2=timeer_out(FLAG)
    def func2(a):
        print(a)
        list1 = [1, 2, 3, 4, 5]
        s = int(input("请输入一个值:"))
        list1.append(s)
        for i in list1:
            print(i, end='   ')
        print('
    ')
        return list1
    #func2=time2(func2)  #使用闭包
    
    
    
    @timeer_out(FLAG)
    def peinrx():
        print("cccccc")
        time.sleep(0.1)
    
    a='开始:'
    ret=func2(a)
    print(ret)
    peinrx()

    2.多个装饰器装饰同一个函数

    def wrapper1(func):
        def inner(*args,**kwargs):
            print('装饰1之前')
            func()
            print("装饰1之后")
        return inner
    
    def wrapper2(func):
        def inner(*args,**kwargs):
            print("装饰2之前")
            func()
            print("装饰2之后")
        return inner
    
    # @wrapper2
    # @wrapper1
    # def f():
    #     print("被装饰的函数")
    #
    # f()
    # 装饰2之前
    # 装饰1之前
    # 被装饰的函数
    # 装饰1之后
    # 装饰2之后
    
    @wrapper1
    @wrapper2
    def f():
        print("被装饰的函数")
    
    f()
    # 装饰1之前
    # 装饰2之前
    # 被装饰的函数
    # 装饰2之后
    # 装饰1之后

    3.一个简单的爬取网页的示例
      本来是不需要自己创建那个文件的,f=open那一行,但不知为何我的pycharm会报错,无奈之下先这么写了

    import os
    from urllib.request import urlopen
    def cache(func):
        def inner(*args,**kwargs):
            #判断
            if os.path.getsize('webcache'):     #判断是否已经有函数
                with open('webcache', "rb") as f:
                    return f.read()
            ######
            ret=func(*args,**kwargs)
            with open('webcache',"wb") as f:
                f.write(b'---'+ret)           #已经存在的,所以
            return ret
        return inner
    
    
    @cache
    def get(url):
        code=urlopen(url).read()   #这是一个bytes
        return code
    
    f=open('webcache',"ab")
    f.close()
    ret=get('http://www.baidu.com')
    print(ret)
    ret=get('http://www.baidu.com')
    print(ret)
    ret=get('http://www.baidu.com')
    print(ret)
    ret=get('http://www.baidu.com')
    print(ret)
    ret=get('http://www.sanguosha.com')
    print(ret)

    4.第二个示例

    #1.编写装饰器,为多个函数加上认证的功能,(用户的账号密码来源于文件)。
    要求成功登陆一次,后续的函数无需输入用户名和密码 #只能创建一个全局变量,否则adddel切换就要在输入
    #2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
    FLAG=False
    def login(func):
        def inner(*args,**kwargs):
            global FLAG
            '''登陆程序'''
            if FLAG:        #如果已经是登陆成功了,就先走了,不需要输入
                with open('log','a',encoding='utf-8') as f:
                    f.write(func.__name__+'
    ')
                ret = func(*args, **kwargs)
                return ret
            else:
               username=input("用户名:")
               password=input("密码:")
               if username=='usern' and password=='passw':
                  FLAG=True
                  with open('log', 'a', encoding='utf-8') as f:
                      f.write(func.__name__ + '
    ')
                  ret=func(*args,**kwargs)
                  return ret
               else:
                  print("登陆失败!")
        return inner
    
    @login
    def shoplist_add():
        print("增加一件物品")
    
    @login
    def shoplist_del():
        print("删除一件物品")
    
    
    while(1):
        a=int(input("请选择操作  1.增加  2.删除  3.退出
    "))
        if a==1:
            shoplist_add()
        elif a==2:
            shoplist_del()
        elif a==3:
            break

     5.再来一个示例。

      介绍两个函数__name__和__doc__

    #记现象
    #functools.wraps
    #带参数的装饰器
    #多个装饰器装饰同一个函数
    #有很多个函数都用装饰器装饰过了,现在要全部去掉装饰,然后又重新再加上装饰
    
    # def outer(*args,**kwargs):
    #     print(args)
    #     print(*args)
    #
    #
    # outer(1,2,[1,2],3,4,**{'name':9})    #outer(*[1,2,3,4])   #outer(
    # # (1, 2, 3, 4)
    # 1 2 3 4    第二个变成散的
    #接收就是聚合,使用就要打散,**kwargs,用*kwargs就是打散
    
    flag1=1
    
    from functools import wraps
    def wrapper(func):
        @wraps(func)             #给内部的函数装饰一下,使holiday()原函数仍然存在。就和inner有区别
        def inner(*args,**kwargs):
            print("之前")
            ret=func(*args,**kwargs)
            print("之后")
            return ret
        return inner
    
    @wrapper
    def holiday(day):
        x=input("你想放几天假?")
        print("不是放%s天假,而是一共放%s天假"%(day,x))
        return x
    
    ret=holiday(2)
    print(ret)
    print(holiday.__name__)
    
    falg2=2
    #
    # def func2():
    #     #打印
    #     '''
    #     只要胆子大,天天都是假
    #     :return:
    #     '''
    #     print("cccc")
    #
    # print(func2.__name__)   #查看函数名
    # print(func2.__doc__)    #查看注释
  • 相关阅读:
    堆、栈及静态数据区详解
    新浪云上传代码包
    主机屋MySQL数据库链接
    Doctype作用?严格模式与混杂模式如何区分?它们有何意义?
    height 与 min-height 的继承
    @media 照成的问题
    img 在chrome和Firefox下的兼容性
    Ionic
    setInterval()和setTimeout()可以接收更多的参数
    angularJs 模拟jQuery中的this
  • 原文地址:https://www.cnblogs.com/lowislucifer/p/10979749.html
Copyright © 2020-2023  润新知