zoukankan      html  css  js  c++  java
  • 装饰器进阶和迭代器

    装饰器进阶和迭代器

    昨日补充

    可变类型,直接在函数内部调用

    不可变类型,需要在函数内部调用,要使用global

    叠加装饰器:

    每一个新的功能都应该写一个新的装饰器

    需求:

    为被装饰对象,添加统计时间与登录认证的功能

    # 登录认证
    
    import time
    
    
    def re_login():
        with open('a.txt', 'r', encoding='utf-8') as rf:
            data = rf.read()
            data1 = data.strip('
    ').split('|')
            data2 = ''.join(data1)
            data3 = data2.split('
    ')
        return data3
    
        # print(data3)
    
    
    # 登录认证装饰器
    def login(func):
        def inner1(*args, **kwargs):
            username = input('请输入用户名:').strip()
            password = input("请输入密码:").strip()
    
            res = re_login()
    
            if username + password in res:
                print('恭喜您,登录成功!')
                re = func(*args, **kwargs)
                return re
    
            else:
                print('对不起,登录失败!')
                re = func(*args, **kwargs)
                return re
    
        return inner1
    
    
    # 统计时间装饰器
    def time_record(func):
        def inner2(*args, **kwargs):
            print('开始统计!')
            start_time = time.time()
            res = func(*args, **kwargs)
            end_time = time.time()
            print(f'执行时间:{end_time - start_time}')
            return res
    
        return inner2
    
    
    # @login  # inner1=inner(inner2)
    # @time_record  # inner2
    
    @time_record
    @login
    def func():
        print('开始下载电影!')
        time.sleep(5)
        print('下载电影结束!')
    
    
    func()
    
    
    开始统计!
    请输入用户名:godlover
    请输入密码:123456
    恭喜您,登录成功!
    开始下载电影!
    下载电影结束!
    执行时间:11.740200519561768
    
    
    
    

    什么是叠加装饰器:

    在同一个被装饰对象中,添加多个装饰器,并执行

    @装饰1

    @装饰2

    def 被装饰对象():

    ​ pass

    ps:装饰器在调用被装饰对象时才添加功能

    装饰顺序:从下至上

    执行顺序:从上至下

    编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码
    
    
    info_dict1 = {
        'name_info': None
    }
    
    
    def re_login():
        username = input('请输入用户名:').strip()
        password = input('请输入密码:').strip()
        with open('a.txt', encoding='utf-8') as f:
            for line in f:
                # print(line)
                name, pwd = line.strip('
    ').split('|')
                if username == name and password == pwd:
                    print('登录成功!')
                    info_dict1['name_info'] = name
                else:
                    print('登录失败!')
    
    
    def login(func):
        def inner(*args, **kwargs):
            if info_dict1.get('name_info'):
                print('免密登录成功!')
                res = func(*args, **kwargs)
                return res
            else:
                re_login()
    
        return inner
    
    
    @login
    def func1():
        print(1)
    
    
    @login
    def func2():
        print(2)
    
    
    @login
    def func3():
        print(3)
    
    
    func1()
    func2()
    func3()
    
    
    
    
    请输入用户名:godlover
    请输入密码:123456
    登录成功!
    登录失败!
    免密登录成功!
    2
    免密登录成功!
    3
    
    
    
    叠加装饰器的理解
    内部的具体运行方式
    
    
    def wrapper1(func):
        def inner1(*args, **kwargs):
            print('1-----start')
            # 被装饰对象在被调用时,如果还有其他装饰器,则会先执行其他装饰器中的inner
            res = func(*args, **kwargs)
            print('1-----end')
            print(res)
            return res
    
        print(1)
        return inner1
    
    
    def wrapper2(func):
        def inner2(*args, **kwargs):
            print('2-----start')
            res = func(*args, **kwargs)
            print('2-----end')
            print(res)
            return res
    
        print(2)
    
        return inner2
    
    
    def wrapper3(func):
        def inner3(*args, **kwargs):
            print('3-----start')
            res = func(*args, **kwargs)
            print('3-----end')
            print(res)
            return res
    
    
        print(3)
    
        return inner3
    
    
    @wrapper1  # 3
    @wrapper2  # 2
    @wrapper3  # 1
    def func():
        print('from func')
        return 1
    
    
    func()
    
    
    3
    2
    1
    1-----start
    2-----start
    3-----start
    from func
    3-----end
    1
    2-----end
    1
    1-----end
    1
    
    
    
    
    

    ps:

    无论inner中出现任何判断,都要返回fun(*args,**kwargs)的结果

    当被装饰器对象还有其他装饰器时跳过直接执行inner

    无参装饰器:

    装饰在被装饰对象时,没有传参数的装饰器

    @wrapper

    有参装饰器:

    @wrapper('参数')

    用途:

    在某些时候我们需要给用户的权限进行分类

    # 调用时@wrapper('参数1')
    def user_auth(user_role):
        def wrapper(func):
            def inner(*args, **kwargs):
                if user_role == 'SVIP':
                    print(1)
                    res = func(*args, **kwargs)
                    return res
                elif user_role == '普通用户':
                    print(2)
                    res = func(*args, **kwargs)
                    return res
    
            return inner
    
        return wrapper
    
    
    # @user_auth('SVIP')  # 相当于@和后面的分开,先执行函数user_auth,返回wrapper,再将@和wrapper结合起来,返回inner
    # def func():
    #     print('from func')
    #
    #
    # func()
    
    @user_auth('普通用户')
    def func():
        print('from func')
    
    
    func()
    
    
    
    2
    from func
    

    wraps:是一种修复工具,修复地是被装饰对象的空间

    例如查看函数内部的注释:

    from functools import wraps
    
    
    def wrapper(func):
        @wraps(func)  # 是一个修复工具,用来修复被装饰对象的空间
        def inner(*args, **kwargs):
            '''
            这里是inner的注释
            :param args:
            :param kwargs:
            :return:
            '''
            res = func(*args, **kwargs)
            return res
    
        return inner
    
    
    @wrapper
    def func():
        '''
        这里是func的注释
        :return:
        '''
        print('from func')
    
    
    print(func.__doc__)
    
    
    
       这里是func的注释
        :return:
    

    迭代器

    迭代器的工具

    迭代:指的是重复迭代,每一个迭代的结果都是基于上一次的结果而来的

    迭代器:指的是迭代取值的工具

    可迭代对象:所有的序列类型:str,list,dict,tuple,set,f

    什么是可迭代对象:

    凡是内部有_ iter _()方法的都是可迭代对象

    什么是迭代器对象:

    通过可迭代对象._ iter _()方法的返回值就是迭代器对象

    如何迭代取值:

    迭代器对象._ next _()

    ps:迭代器中的值取完时,会报错StopIteration

    list =['jason','sean','egon','tank']
    iter_list1 = list._iter_()
    while True:
        #try:捕获异常
        try:
            print(iter_list1._next_())#报错
        except StopIteration:
            break
            
    

    迭代器的优缺点:

    优点:

    1.不依赖于索引,迭代取值

    2.节省内存空间

    缺点:

    1.取指定的某个值比较麻烦,每次取值都要从第一个值开始,无法通过索引取值

    2.不能够通过len()计算长度

    总结

    可迭代对象 vs 迭代器对象

    获取可迭代对象:

    定义序列类型

    特点:

    凡是内置有_ iter _()方法的都是可迭代对象

    获取迭代器对象:

    过可迭代对象._ iter _()方法的返回值就是迭代器对象

    特点:

    内置有_ next _()方法

    for 循环的原理

    in自动将可迭代对象调用_iter_()方法变成迭代器对象

    for i in 可迭代对象:
    #迭代器对象调用_next_()方法取值
    print(I)
    里面也调用捕获异常机制

    迭代器对象的本质是一个可迭代对象

    文件本质既是可迭代对象又是迭代器对象

    文件计较特殊:文件读取出来的时候就是一个迭代器对象

    最后注意:

    可迭代器对象不一定是迭代器对象(文件既是可迭代对象,也是迭代器对象,但是其他可迭代器不是迭代器对象)

    但是迭代器对象一定是可迭代对象

  • 相关阅读:
    最近学习下,nohup和&的区别
    java 关键字
    iOS之事件穿透
    排序算法——快速排序
    分布式-选举算法
    分布式选举算法
    SolrCloud 分布式集群部署步骤
    linux 启动两个tomcat
    solr安装-tomcat+solrCloud构建稳健solr集群
    JAVA 中BIO,NIO,AIO的理解
  • 原文地址:https://www.cnblogs.com/godlover/p/11854158.html
Copyright © 2011-2022 走看看