六、迭代器、生成器和装饰器

1.迭代器

  • 定义

    能被next()函数进行调用且不断返回下一个值的对象。其内置方法中包含__iter__(返回迭代器本身)和__next__(返回容器的下一个元素)。

  • 特征

    迭代器会生成惰性序列,它通过计算把值依次的返回,一边循环一边计算,而不是一次性得到所有的数据。

  • 优点

    需要数据的时候,一次取一个,可以在很大程度上节省内容空间,而不是一次性把所有的数据存入内存中;此外,可以遍历无限量的数据。

  • 创建

    使用iter()函数来创建。

    string = iter('abcd')
    print(next(string))
    print(next(string))
    print(next(string))
    print(next(string))
    # 遍历完成之后继调用
    print(next(string))
    
    # 输出结果
    StopIteration
    a
    b
    c
    d
    
    # 注意:当遍历完序列时,会引发一个StopIteration异常。使用for循环可以规避整个问题(for循环的底层使用了next方法)。
    string = iter('abcd')
    for item in string:
        print(item)
    # 输出结果
    a
    b
    c
    d

2. 生成器

  • 定义

    包含了yield语句的函数。

  • 特征

    执行生成器函数时,其内部代码不执行,而是返回一个生成器对象(特殊的迭代器)。生成器可以暂停函数并返回一个中间结果(遇到yield本次循环就终止,并返回yield后的值),可以被for循环或者用next函数逐个取值。

  • 格式

    # 格式一
    def fun():
        print('第一次执行')
        yield 1
        print('第二次执行')
        yield 2
        print('第三次执行')
        yield 3
    
    result = fun()
    print(result, type(result))
    for i in result:
        print(i)
    
    
    # 格式二
    def fun():
        print('第一次执行')
        yield 1
        print('第二次执行')
        yield 2
        print('第三次执行')
        yield 3
    
    result = fun()
    print(next(result))
    print(next(result))
    print(next(result))
    
    
    # 输出结果
    <generator object fun at 0x000001A203DD5A20> <class 'generator'>
    第一次执行
    1
    第二次执行
    2
    第三次执行
    3
  • 注意

    生成器中不能包含return语句,遇到return语句则会结束生成器。

    
    def fun():
        print('第一次执行')
        yield 1
        print('第二次执行')
        yield 2
        return 123
        print('第三次执行')
        yield 3
    
    for i in fun():
        print(i)
    
    # 输出结果
    第一次执行
    1
    第二次执行
    2
  • 生成器推导式

    result = (lambda: i ** 2 for i in range(1, 5))
    print(type(result))
    for i in result:
        print(i())
    
    # 输出结果
    <class 'generator'>
    1
    4
    9
    16
    
    
    # 对比列表推导式
    result = [lambda: i ** 2 for i in range(1, 5)]
    print(type(result))
    for i in result:
        print(i())
    
    # 输出结果
    <class 'list'>
    16
    16
    16
    16

3. 装饰器

  • 定义

    在不改变原函数内部代码的基础上,在函数执行之前和之后自动执行某个功能。

  • 装饰器编写格式

    def 外层函数(传入参数):
        def 内层函数(*args, **kwargs):
            result = 传入参数(*args, **kwargs)
            return result
        return 内层函数
  • 装饰器应用格式

    @外层函数
    def index():
        pass
    
    index()
  • 作用

    # 和index函自身相比,使用装饰器之后,执行index函数可以在原函数的基础上多执行print('执行原函数前')和print('执行原函数后')两条语句,此处是以最简单的方式来进行说明,完全可以根据需求将这两个语句换成功能更复杂的语句块。
    
    def 外层函数(传入参数):
        def 内层函数(*args, **kwargs):
            print('执行原函数前')
            result = 传入参数(*args, **kwargs) # 执行原函数并返回值
            print('执行原函数后')
            return result
        return 内层函数
    
    @外层函数
    def index():
        pass
    
    index()
  • 例子

    def fun(arg):
        def inner():
            print('执行函数前添加的功能:', 1)
            v = arg()
            print('执行函数后添加的功能:', 3)
            return v
        return inner
    
    # 第一步:执行fun函数并将下面的函数作为参数传递,相当于:fun(index)
    # 第二步:将fun的返回值重新赋值给下面的函数名,相当于:index = fun(index)
    @fun
    def index():
        print('函数自己的功能:', 2)
        return 666
    
    index()
    
    # 输出结果为
    执行函数前添加的功能: 1
    函数自己的功能: 2
    执行函数后添加的功能: 3
    
    # 若没有@fun语句(没有使用装饰器),输出结果为
    函数自己的功能: 2
  • 带参数的装饰器

    # 可以用于连续多次重复执行函数
    def with_parameter(count):
        def outer(arg):
            def inner():
                for i in range(count):
                    print('\n第%d次执行' % (i + 1))
                    print('执行函数前添加的功能:', 1)
                    v = arg()
                    print('执行函数后添加的功能:', 3)
                return v
            return inner
        return outer
    
    # 相当于:index = with_parameter(3)(index)
    @with_parameter(3)
    def index():
        print('函数自己的功能:', 2)
        return 666
    
    result = index()
    print('\n函数最后的返回结果:', result)
    
    # 输出结果
    
    第1次执行
    执行函数前添加的功能: 1
    函数自己的功能: 2
    执行函数后添加的功能: 3
    
    第2次执行
    执行函数前添加的功能: 1
    函数自己的功能: 2
    执行函数后添加的功能: 3
    
    第3次执行
    执行函数前添加的功能: 1
    函数自己的功能: 2
    执行函数后添加的功能: 3
    
    函数最后的返回结果: 666

猜你喜欢

转载自www.cnblogs.com/aaron-zhou/p/11802504.html