• day14 带参装饰器、迭代器、生成器


    """
    今日内容:
        1、带参装饰器及warps
        2、迭代器
        3、生成器
    """
    
    """
    # 一、带参装饰器及warps系统装饰器
    # 1、为什么需要带参装饰器?
        -- 昨天的内容已经讲了装饰器,但是讲的都是增加的函数不需要外界传人参数,如果装饰器也需要外界传入参数呢?
        -- 此时就需要带参装饰器
        
    # 2、装饰器的推导过程
        -- 如果添加的功能也需要外界传入参数时,参数应该如何通过谁进行传递呢?
        -- 如果通过inner传入参数,因为inner中为可变长参数,所以会直接将参数传递给原函数,此方法不可行
        -- 如果通过 outter 进行传入,那么需要在func旁再增加参数,在调用outter时就需要将参数传递进去,此时就不能使用语法糖,破坏装饰器的整体结构
        -- 所以,最后的办法是根据闭包的方法将整个装饰器作为闭包,在外界增加一层函数,最后将整个装饰器作为返回值进行返回,就可以为装饰器传递参数了
        
    def wrap(info):
        def outer(func):
            # info = 0
            def inner(*args, **kwargs):
                print('新:拓展的新功能,可能也需要外界的参数%s' % info)
                res = func(*args, **kwargs)
                return res
            return inner
        return outer
        
    -- 此时,整个 warp 就是一个带参装饰器,其语法糖为 @wrap("新功能需要的参数")
    
    @wrap('外部参数')
    def fn(): pass
    
    # 3、什么是wraps装饰器?
        -- 系统自带的装饰器,用来在用户查询被装饰函数的doc文档时,将被装饰函数的文档注释打印给用户
        -- 因为当我们使用装饰器为某个功能进行装饰时,最后的调用过程虽然看着还是原函数,但是我们已经为原函数进行了重新复制,此时再使用查询原函数的doc等内置功能时,访问的实际是装饰器
        -- @warps装饰器的作用就是将原函数的doc等内置功能传递给用户,彻底伪装好装饰器
    
    # 4、如何使用warp装饰器?
    from functools import wraps
    def outer(func):
        @wraps(func)
        def inner(*args, **kwargs):
           
            res = func(*args, **kwargs)
            return res
        return inner
    
    @outer
    def fn(): pass
    
    """
    
    """
    # 二、迭代器
    # 1、什么是迭代器?
        -- 迭代器是一种可以不依赖于索引取值的容器
        
    # 2、迭代器的优缺点:
        -- 迭代器优点:可以不用依赖索引取值
        -- 迭代器缺点:只能从前往后依次取值
    
    # 3、迭代器对象与可迭代对象
        -- 可迭代对象:具有__iter__()方法的对象就叫做可迭代对象,可迭代对象可以通过__iter__()方法转换成迭代器对象
        
            ls = [4, 1, 5, 2, 3]
            res = ls.__iter__()  # => 可迭代对象
            print(res)  # <list_iterator object at 0x000002732B0C7470>
    
        -- 迭代器对象:具有__next__()方法的对象叫做迭代器对象,迭代器对象可以通过__next__()方法进行取值,一次只能取出一个值
        
            with open('1.txt', 'rb') as f:
            res = f.__next__()  # 文件中的第一行内容
            print(res)
            res = f.__next__()  # 文件中的第二行内容
            print(res)
            
    # 4、for循环迭代器
        -- 迭代器取值时的问题
            -- 在我们从迭代器对象中取值时,可以使用__next__()从迭代器中取值,但是,每使用一次__next__()方法才会取出一个值,那么怎么把迭代器中的值全部取出来呢?
            -- 在使用__next__()进行取值时,如果取出所有的值后还有__next__()方法,就会抛出异常
            
        -- for循环迭代器
            -- 从迭代器中取值,可以依次取出迭代器中所有的值,
            -- for循环中封装了异常处理机制,会自动处理取去所有值后抛出的异常
            -- for循环会将 in 后面的可迭代对象或迭代器对象直接添加.__iter__()方法
            
        -- for循环迭代器的工作原理:
            for v in obj: pass
            -- 获取obj.__iter__()的结果,就是得到要操作的迭代器对象
            -- 迭代器对象通过__next__()方法进行取值,依次将当前循环的取值结果赋值给v
            -- 当取值抛异常,自动处理StopIteration异常结束取值循环
    
    # 5、枚举器 (enumerate)
        -- 枚举器就是给迭代器中的取值结果加索引的,当使用枚举器进行取值时,每次取值时会自动为取的值加上取值索引。
            s = 'abc'
            for v in enumerate(s):
                print(v)  # (0 'a') | (1 'b') | (2 'c')
    
    """
    
    """
    # 四、生成器
    # 1、什么是生成器?
        -- 生成器就是可以自定义的迭代器
    # 2、如何自定义生成器?
        -- 我们可以使用函数进行声明,再使用 yeild 返回值,这样在使用函数名()时就不是调用函数,而是生成迭代器对象
        -- 在有yield关键字时,再使用return关键字,return关键字不起任何作用
        -- 使用yeild关键字生成迭代器时,当使用__next__()进行取值时,每次只会返回一个yeild后的值,并卡在原地,不会执行后面的代码,当再次遇到__next__()时才会继续向下执行
        def fn():
            yield 1
            yield 3
            yield 5
        obj = fn()
        obj.__next__()  # 从开始往下执行,遇到第一个yield停止,拿到yield的返回值
        obj.__next__()  # 从上一次停止的yield往下执行,在再遇到的yield时停止,拿到当前停止的yield的返回值
        ...              # 以此类推,直到无法获得下一个yield,抛StopIteration异常
        
        -- 我们自定义的生成器可以使用for循环直接取值。
        
    # 3、生成器案例
    
    # 案例一:创建生成器,从其取值,依次得到1! 2! 3! ...,可无限取值生成器。
    def jiecheng():
        ji = 1
        count = 1
        while True:
            ji *= count
            yield ji
            count += 1
    
    obj = jiecheng()
    print(obj.__next__())
    print(obj.__next__())
    print(obj.__next__())  # 可以无限取
    
    
    # 案例二:
    # 自定义结束条件生成器
    def jiecheng_num(num):
        ji = 1
        for i in range(1, num + 1):
            ji *= i
            yield ji
        # ...
    
    obj = jiecheng_num(3)
    print(obj.__next__())
    print(obj.__next__())
    print(obj.__next__())
    print(obj.__next__())  # 有异常了
    
    
    for v in jiecheng_num(5):
        print(v)  # 会自动处理异常停止
    
    
    # 案例三:
    # 自制的range函数
    def my_range(num):  # => [0, 1, 2, ..., num - 1]
        count = 0
        while count < num:
            yield count
            count += 1
    
    for v in my_range(10):
        print(v, end=' ')
    
    print(list(my_range(10)))
    """
  • 相关阅读:
    配置Domino CA以支持SSL
    如何在Notes中撰寫JavaServlet程式
    Lotus 技术点之导入
    Lotus Domino R5开发心得
    Domino中用可定制表单显示定制的错误消息
    ExtJs GridPanel 完整实例
    当程序员变成软件项目经理
    SQL Server 索引结构及其使用
    C#事务处理
    on用onpropertychange,oninput事件解决onchange事件的不足
  • 原文地址:https://www.cnblogs.com/lice-blog/p/10792235.html
Copyright © 2020-2023  润新知