zoukankan      html  css  js  c++  java
  • day12:装饰器的进阶

    1,三元运算符:变量 = 条件返回True的结果 if 条件 else 条件返回false的结果;必须要有结果;必须要有if和else,只能是简单的情况。

    2,传参包起来,星号打散

    def outer(*args):
        print(args)
        print(*args)
    
    outer(1,2,3,4) #==> outer(*(1,2,3,4)) *打散,传参的时候,默认包起来包成一个元祖,拿出来用的时候,加*号打散
    
    outer(*[1,2,3,4])

    3,print为何可以接收各种参数,因为默认里面参数加了*args,内置函数是用C语言写的

    4,昨天作业一

    # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
    # 要求登录成功一次,后续的函数都无需再输入用户名和密码
    
    # 自己的版本
    FLAG = False
    def wrapper(func):
        def inner(*args,**kwargs):
            global FLAG
            if FLAG == False:  # not FLAG
                usrname = input("please input username:")
                li = []
                with open("file.txt",encoding="utf-8") as f1:
                    for line in f1:
                        li.append(line.strip())
                if li[0] == usrname :
                    pwd = input("please input password:")
                    if li[1] == pwd:
                        print("登录成功")
                        FLAG = True
                    else:
                        FLAG = False
                        print("登录失败")
                        return
                else:
                    FLAG = False
                    print("登录失败")
                    return
    
            ret = func(*args,**kwargs)
            return ret
        return inner
    
    
    @wrapper
    def func():
        print("in func")
    
    @wrapper
    def func1():
        print("in func1")
    
    @wrapper
    def func2():
        print("in func2")
    
    func()
    func1()
    func2()
    
    # 可以看到这儿只认证了一次 运行结果: please input username:lisa please input password:
    123 登录成功 in func in func1 in func2
    1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),
    # 要求登录成功一次,后续的函数都无需再输入用户名和密码
    
    # 老师的版本
    # FLAG = False
    # def login(func):
    #     def inner(*args,**kwargs):
    #         global FLAG
    #         '''登录程序'''
    #         if FLAG:
    #             ret = func(*args, **kwargs)  # func是被装饰的函数
    #             return ret
    #         else:
    #             username = input('username : ')
    #             password = input('password : ')
    #             if username == 'boss_gold' and password == '22222':
    #                 FLAG = True
    #                 ret = func(*args,**kwargs)      #func是被装饰的函数
    #                 return ret
    #             else:
    #                 print('登录失败')
    #     return inner
    #
    # @login
    # def shoplist_add():
    #     print('增加一件物品')
    #
    # @login
    # def shoplist_del():
    #     print('删除一件物品')
    #
    # shoplist_add()
    # shoplist_del()

    5,昨天作业二:

    # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
    # 自己的版本
    def wrapper(func):
        def inner(*args,**kwargs):
            funcname = func.__name__
            with open("func_call_record.txt","a+",encoding="utf-8") as f1:
                f1.write(funcname+"
    ")
            ret = func(*args,**kwargs)
            return ret
        return inner
    
    
    @wrapper
    def func():
        pass
    
    @wrapper
    def func1():
        pass
    
    @wrapper
    def func2():
        pass
    
    func1()
    func2()
    func()
    func1()
    # 2.编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称写入文件
    # 老师的版本
    def log(func):
        def inner(*args,**kwargs):
            with open('log','a',encoding='utf-8') as f:
                f.write(func.__name__+'
    ')
            ret = func(*args,**kwargs)
            return ret
        return inner
    
    @log
    def shoplist_add():
        print('增加一件物品')
    
    @log
    def shoplist_del():
        print('删除一件物品')
    
    shoplist_add()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()

    6,昨天作业三:

    # 进阶作业(选做):
    # 1.编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
    # 2.为题目1编写装饰器,实现缓存网页内容的功能:
    # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中
    
    #  老师的版本
    from urllib.request import urlopen
    import os
    
    def cache(func):
        def inner(*args,**kwargs):
            if os.path.getsize("web_cache.txt"):
                with open("web_cache.txt","rb") as f:
                    return f.read()
            ret = func(*args,**kwargs)
            with open("web_cache.txt",'wb') as f:
                f.write(b"******"+ret)
            return ret
    
        return inner
    
    
    @cache
    def get_code(url):
        code =urlopen(url).read()
        return code
    
    code = get_code('http://www.baidu.com')  # 路径要给全
    print(code)
    code = get_code('http://www.baidu.com')  # 路径要给全
    print(code)
    code = get_code('http://www.baidu.com')  # 路径要给全
    print(code)

    7,被装饰之后,保留原函数的各种属性

    def wrapper(f):
        def inner(*args,**kwargs):
            '''
            我是inner函数
            :return:
            '''
            ret = f(*args,**kwargs)
            return ret
        return inner
    
    @wrapper
    def func():
        '''
        我是被修饰的函数func
        :return:
        '''
    
        pass
    
    print(func.__name__)
    print(func.__doc__)
    
    运行结果:
    inner
    
            我是inner函数
            :return:
            

    8,从上一步看出,打印出来的信息都是和inner相关的,这并不是我想要的,我想要的是被修饰函数相关的,怎么办呢?

    from functools import wraps
    
    
    def wrapper(f):
        @wraps(f)
        def inner(*args,**kwargs):
            '''
            我是inner函数
            :return:
            '''
            ret = f(*args,**kwargs)
            return ret
        return inner
    
    @wrapper
    def func():
        '''
        我是被修饰的函数func
        :return:
        '''
    
        pass
    
    print(func.__name__)
    print(func.__doc__)
    
    # 看出来代码哪里变化了吗?
     运行结果:
    func
    
        我是被修饰的函数func
        :return:

    9,带参数的装饰器,其实是又加了一层,三层其实是最多的了,作用就一个,传递进去一个或者多个参数,然后返回内层函数。

    import time
    
    FLAG = False
    def timer_off(flag):
        def timer(f):
            def inner():
                if flag:
                    starttime = time.time()
                    ret = f()
                    endtime = time.time()
                    duration = endtime - starttime
                    print(duration)
                    return ret
                else:
                    ret = f()
                    return ret
            return inner
        return timer
    
    FLAG = True
    @timer_off(FLAG)   #timer_off(FLAG) ==timer   @time == func=timer(func) 也就是inner
    def func():
        time.sleep(0.1)
        print("i am func")
    
    func()

    10,老师推荐了两本书:《Python核心编程》第二版和《流畅的Python》 先看第一本,第二本比较讲的比较深

    11,多个装饰器装饰一个函数,弄清楚是谁装饰了谁,执行顺序

    def wrapper1(f):
        def inner1():
            print("before inner1")
            ret = f()
            print("after inner1")
            return ret
        return inner1
    
    
    def wrapper2(f):
        def inner2():
            print("before inner2")
            ret = f()
            print("after inner2")
            return ret
        return inner2
    
    @wrapper2
    @wrapper1
    def func():
        print("i am func")
    
    func()
    运行结果:
    before inner2
    before inner1
    i am func
    after inner1
    after inner2
    def wrapper1(f):
        def inner1():
            print("before inner1")
            ret = f()
            print("after inner1")
            return ret
        return inner1
    
    
    def wrapper2(f):
        def inner2():
            print("before inner2")
            ret = f()
            print("after inner2")
            return ret
        return inner2
    
    @wrapper1
    @wrapper2
    def func():
        print("i am func")
    
    func()
    运行结果:
    before inner1
    before inner2
    i am func
    after inner2
    after inner
  • 相关阅读:
    Python 安装、循环语句、数据类型(一)
    Python 字符、整型、列表字典等操作(二)
    JAVA实现文章的上一篇下一篇
    什么是公钥、私钥、密码、助记词
    XSS跨站网络攻击
    区块链相关知识
    冷钱包
    .NET 后台提交POST请求
    邮件的发送
    数据库中字段类型对应的C#中的数据类型
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10081008.html
Copyright © 2011-2022 走看看