• Day7:有参装饰器、迭代器


    一.有参装饰器

    昨天的作业当中,做一个认证的装饰器,认证成功一次,执行其他函数不再进行认证。使用的装饰器为无参装饰器。

    db_path=r'E:PycharmProjectsqz5db.txt'
    user_dic={
        'egon':'123',
        'alex':'alex3714',
        'wupeiqi':'123',
        'yunahao':'123',
    }
    with open(db_path,'w',encoding='utf-8') as f:
        f.write(str(user_dic))
    login_dic={
        'user':None,
        'status':False,
    }
    def auth(func):    #装饰器没有传入参数
        def wrapper(*args,**kwargs):
            with open(db_path,'r',encoding='utf-8') as f:
                user_dic=eval(f.read())
            while not login_dic['user'] and not login_dic['status']:
                name = input('name:')
                pwd = input('password:')
                if name in user_dic:
                    if pwd==user_dic[name]:
                        print('login successful')
                        login_dic['user']=name
                        login_dic['status']=True
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('password err')
                        continue
                else:print('no user')
            else:
                res = func(*args, **kwargs)
                return res
        return wrapper
    @auth
    def index():
        print('welcome to index')
    @auth
    def home(name):
        print('welcome %s to home page'%name)
    index()
    home('egon')

    有不通的认证方式:比如ldap认证,mysql认证。现在要求不同的函数要用不通的认证方式,就需要用有参装饰器。有参装饰器也就是在无参装饰器外面再包一层函数,带上参数。

    def deco(auth_type='file'):
        def auth(func):
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    print('文件的认证方式')
                elif auth_type == 'ldap':
                    print('ldap的认证方式')
                elif auth_type == 'mysql':
                    print('mysql的认证方式')
                else:
                    print('不知道的认证方式')
            return wrapper
        return auth
    @deco(auth_type='abc')  
    def index():
        print('welcome to index ')
    @deco()
    def home(name):
        print('welcome to %s home page' %name)
    index()
    home('egon')
    
    运行结果:
    不知道的认证方式
    文件的认证方式

    二.迭代器

    1.迭代

    迭代就是重复,下一次的重复是基于上一次的结果

    2.迭代器

    python为了提供一种不依赖于索引的迭代方式,
    python会为一些对象内置__iter__方法
    obj.__iter__称为可迭代的对象

    可以直接作用于for循环的数据类型有以下几种:

    一类是集合数据类型,如listtupledictsetstr等;

    一类是generator,包括生成器和带yield的generator function。

    这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

    可以使用isinstance()判断一个对象是否是Iterable对象:

    >>> from collections import Iterable
    >>> isinstance([], Iterable)
    True
    >>> isinstance({}, Iterable)
    True
    >>> isinstance('abc', Iterable)
    True
    >>> isinstance((x for x in range(10)), Iterable)
    True
    >>> isinstance(100, Iterable)
    False

    而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

    可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator

    可以使用isinstance()判断一个对象是否是Iterator对象:

    >>> from collections import Iterator
    >>> isinstance((x for x in range(10)), Iterator)
    True
    >>> isinstance([], Iterator)
    False
    >>> isinstance({}, Iterator)
    False
    >>> isinstance('abc', Iterator)
    False

    生成器都是Iterator对象,但listdictstr虽然是Iterable,却不是Iterator

    listdictstrIterable变成Iterator可以使用iter()函数:

    >>> isinstance(iter([]), Iterator)
    True
    >>> isinstance(iter('abc'), Iterator)
    True

    你可能会问,为什么listdictstr等数据类型不是Iterator

    这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

    小结

    凡是可作用于for循环的对象都是Iterable类型;

    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

    集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

    迭代器的优点
    1:提供了一种不依赖于索引的取值方式
    2:惰性计算。节省内存

    迭代器的缺点:
    1:取值不如按照索引取值方便
    2:一次性的。只能往后走不能往前退
    3:无法获取长度

    Python的for循环本质上就是通过不断调用next()函数实现的,例如:

    for x in [1, 2, 3, 4, 5]:
        pass

    实际上完全等价于:

    # 首先获得Iterator对象:
    it = iter([1, 2, 3, 4, 5])
    # 循环:
    while True:
        try:
            # 获得下一个值:
            x = next(it)
        except StopIteration:
            # 遇到StopIteration就退出循环
            break
  • 相关阅读:
    wqs二分
    FLAG区
    Codeforces | CF1033D 【Divisors】
    Nowcoder | [题解-N210]牛客OI月赛2-提高组
    Codeforces | CF1041F 【Ray in the tube】
    Nowcoder | [题解-N189]牛客OI赛制测试赛3
    Codeforces | CF1029F 【Multicolored Markers】
    Codeforces | CF1037D 【Valid BFS?】
    Codeforces | CF1028C 【Rectangles】
    Codeforces | CF1029C 【Maximal Intersection】
  • 原文地址:https://www.cnblogs.com/Vee-Wang/p/7028271.html
Copyright © 2020-2023  润新知