zoukankan      html  css  js  c++  java
  • 装饰器的补充以及迭代器

    装饰器的补充以及迭代器

    一、登录认证功能

    user_info = {
        'user': None
    }
    #登录功能认证
    def login():
        username = input('请输入账号名:').strip()
        password = input('请输入密码:').strip()
        with open(r'a.txt', 'r', encoding='utf-8')as f:
            for line in f:
                f.readline()
                name, pwd = line.strip('
    ').split(':')#交叉赋值返回的是['yafeng','666']
        if username == name and password == pwd:
            print('登录成功!')
            user_info['user'] = username
        else:
            print('登录失败!')
    
    def login_auth(func):
    
        def inner(*args, **kwargs):
            #已经登录,将被装饰对象直接调用并返回
            if user_info.get('user'):#如果在列表里
                res = func(*args, **kwargs)
    
                return res
            else:
                print('请先登录')
                login()
                '''
                注意: 无论inner中出现任何判断,
                最后都要返回“调用后的被装饰对象” func(*args, **kwargs)
                 '''
                res = func(*args, **kwargs)#注意此时一定要返回res,否则from 1 打印不出来
                return res
    
        return inner
    
    
    @login_auth
    def func1():
        print('from 1')
        pass
    
    @login_auth
    def func2():
        print('from 2')
        pass
    @login_auth
    def func3():
        print('from 3')
        pass
    
    while True:
        func1()
        input('请输入操作')
        func2()
        func3()
    

    二、装饰器之叠加装饰器

    有的时候我们想要对一个被装饰函数进行多功能的装饰,虽然我们也可以在一个装饰器中去添加多个功能,但这样就会显得代码很长,可读性不高,而且如果以后我们又想修改这个装饰器函数的功能,我们还得去删除,我们最好的方法就是一个装饰器就固定哪一个功能,我们想要对函数进行多此装饰,那么此时叠加装饰器就派上用场了。

    • 叠加装饰器
    在同一个被装饰对象中,添加多个装饰器,并执行。
    @装饰1
    @装饰2
    @装饰3
    def 被装饰对象():
        pass
    
    注意:叠加装饰器的顺序*****(重要)
    	装饰的顺序:由下到上装饰
        执行的顺序:由上往下
    
    • 叠加器演示
    def wrapper1(func):
        def inner1(*args, **kwargs):
            print('1---start')
            # 被裝飾對象在調用時,如果還有其他裝飾器,會先執行其他裝飾器中的inner
            # inner2
            res = func(*args, **kwargs)
            print('1---end')
            return res
    
        return inner1
    
    
    def wrapper2(func):
        def inner2(*args, **kwargs):
            print('2---start')
            res = func(*args, **kwargs)
            print('2---end')
            return res
    
        return inner2
    
    
    def wrapper3(func):
        def inner3(*args, **kwargs):
            print('3---start')
            res = func(*args, **kwargs)
            print('3---end')
            return res
    
        return inner3
    
    
    '''
    叠加裝飾器的裝飾順序與執行順序:
        - 裝飾順序: 调用wrapper装饰器拿到返回值inner
            由下往上裝飾
    
        - 執行順序: 调用装饰过后的返回值inner
            由上往下執行
    '''
    
    
    @wrapper1  # index《---inner1 = wrapper1(inner2)
    @wrapper2  # inner2 = wrapper2(inner3)
    @wrapper3  # inner3 = wrapper3(index)
    def index():  # 被裝飾對象   # inner1 ---》
        print('from index...')
    
    
    # 正在装饰
    inner3 = wrapper3(index)
    inner2 = wrapper2(inner3)
    inner1 = wrapper1(inner2)
    
    '''
    inner1()
    inner2()
    inner3()
    index()
    '''
    index()  # 此处执行 # inner1() --> inner2() ---> inner3()
    >>>1---start
    2---start
    3---start
    from index...
    3---end
    2---end
    1---end
    
    
    • 有参装饰器

    之前我们用的都是无参装饰器,就是在装饰被装饰对象时,没有传参

    '''
    # 以下是无参装饰器
    @wrapper1  # inner1 = wrapper1(inner2)
    @wrapper2  # inner2 = wrapper2(inner3)
    @wrapper3
    '''
    
    # 有参装饰器: 在某些时候,我们需要给用户的权限进行分类
    '''
    # 以下是有参装饰器
    @wrapper1(参数1)  # inner1 = wrapper1(inner2)
    @wrapper2(参数2)  # inner2 = wrapper2(inner3)
    @wrapper3(参数3)
    '''
    
    
    • 有参装饰器
    def user_auth(user_role):  # 'SVIP'
        def wrapper(func):
            def inner(*args, **kwargs):
                if user_role == 'SVIP':
                    # 添加超级用户的功能
                    res = func(*args, **kwargs)
                    return res
                elif user_role == '普通用户':
                    print('普通用户')
                    # 添加普通用户的功能
                    res = func(*args, **kwargs)
                    return res
    
            return inner
        return wrapper
    
    
    # 被装饰对象
    # @user_auth('SVIP')
    wrapper = user_auth('普通用户')
    @wrapper
    # @user_auth('SVIP')  # wrapper = user_auth('普通用户')
    @wrapper  #<--- 返回结果(wrapper) <---- user_auth()
    def index():
        pass
    index()
    
    
    • wraps
    '''
    wraps: (了解)
        是一个修复工具,修复的是被装饰对象的空间。
        from functools import wraps
    
    '''
    from functools import wraps
    
    
    def wrapper(func):
    
        @wraps(func)  # 修改名称空间: inner ---》 func
        def inner(*args, **kwargs):
            '''
            此处是装饰器的注释
            :param func:
            :return:
            '''
            res = func(*args, **kwargs)
            return res
        return inner  # ---》 func
    
    
    @wrapper
    def index():
        '''
        此处是index函数的注释
        :return:
        '''
        pass
    
    
    print(index)  # 函数对象
    
    # 函数对象.__doc__: 查看函数内部的注释
    print(index.__doc__)  # inner.__doc__
    
    

    三、迭代器

    • 什么是迭代器

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

    x = 10
    while True:
        print(x)
    #这虽然是重复过程,但并没有基于上一次的结果
    
    l = [1,2,3,4]
    n = 0
    while n < len(l):
    	print(l[n])
        n  += 1
    >>>1
    2
    3
    4
    #这才是一个迭代,每次结果基于上一次
    
    

    要想了解迭代,我们还得先了解什么是可迭代对象

    在python中,但凡内置有._iter_()方法的对象都叫可迭代对象所以以下都是可迭代对象:
    str
    list
    dict
    tuple
    set
    file
    
    

    了解了什么是可迭代对象的概念后我们就可以给迭代器下定义了,迭代器指的是更新取值的工具。

    知道了什么是迭代器,什么是可迭代对象以后,我们就可以去说什么是迭代器对象

    迭代器对象:

    可迭代的对象执行.iter()方法得到的返回值就是迭代器对象,接下来我们在用得到的迭代器对象.next()就可以去获取每个元素的值了

    s = {1, 2, 3}
    iter_s = s.__iter__()#iter_s就是迭代器对象
    print(iter_s.__next__())
    print(iter_s.__next__())
    print(iter_s.__next__())
    print(iter_s.__next__())
    >>>Traceback (most recent call last):
      File "D:/python的pycharm/正式课/day12/迭代器.py", line 53, in <module>
        print(iter_s.__next__())
    StopIteration
    1
    2
    3
    
    

    上面我们虽然拿到了每个集合中的元素,但会报错,就是有个StopIteration的错误,该错误指的是当我打印的值超过了我的一个容器中的所有容量的时候会报错,因为已经没有对象让我们访问了,那此时我们能不能即能获取到里面的所有元素,也不报错呢,答案是肯定的。这时就需要用到try

    s = {1, 2, 3}
    iter_s = s.__iter__()#iter_s就是迭代器对象
    while True:
        try:
            print(iter_s.__next__())
    
        except StopIteration:
            break
    >>>1
    2
    3
    
    • 总结比比较

      可迭代的对象:

      ​ 特点:内置有——iter——方法的,就都是可迭代的对象,执行该方法会得到一个迭代器对象

      迭代器对象的特点:

      ​ 内置有——next——方法,每一次执行会拿到迭代器对象中的一个值

      ​ 内置有——iter——方法,执行会得到迭代器本身

      迭代器的特点:

      ​ 优点:提供了一种不依赖于索引取值的方法

      ​ 迭代器会更加节省空间内存

      ​ 缺点:取值麻烦,只能一个一个取

      ​ 无法使用len去获取某个具体的值

  • 相关阅读:
    BZOJ3752 : Hack
    XIV Open Cup named after E.V. Pankratiev. GP of SPb
    XIII Open Cup named after E.V. Pankratiev. GP of Ukraine
    BZOJ2087 : [Poi2010]Sheep
    BZOJ2080 : [Poi2010]Railway
    BZOJ2082 : [Poi2010]Divine divisor
    Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
    XIII Open Cup named after E.V. Pankratiev. GP of Asia and South Caucasus
    XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea
    XIII Open Cup named after E.V. Pankratiev. GP of SPb
  • 原文地址:https://www.cnblogs.com/yafeng666/p/11851961.html
Copyright © 2011-2022 走看看