zoukankan      html  css  js  c++  java
  • Python第六章-函数05-迭代器&生成器


    python作为一个既面向对象,又支持函数式编程的语言,函数的使用方面有很多特点。

    比如:闭包,装饰器,迭代器等

    函数的高级应用

    容器:生活中常见的容器有哪些?袋子,盆子,水杯,书包,铅笔盒。。。

    容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个的迭代获取,可以用in,not in等关键字判断某个元素是否包含在容器中。在python中常见的容器对象有:

    list, tuple, dict, str, set

    容器你可以把它看做一个房子,一个柜子,一个盒子,里面可以塞任何东西,从技术角度来说,当他可以用来询问某个元素是否包含在其中时,那么这个对象就可以看做一个容器。

    1 in [1, 2, 3]   # True
    4 not in [1, 2, 3, 4]   # False
    4 in {1, 2, 3}   # False
    4 not in {1, 2, 3, 4}   # False
    

    一、迭代器

    回想一下,到目前为止,能用for循环进行遍历的数据类型主要有哪些呢?dict,tuple,str,set,list

    1.1 可迭代对象

    可迭代对象和容器一样是一种通俗的叫法,并不是指某种具体的数据类型,list是可迭代对象,dict是可迭代对象,set也是可迭代对象。

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

    前面说的序列和集合类型也是基于这个原理

    那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:

    from collections import Iterable
    
    # str是否可迭代
    print(isinstance("abc", Iterable))  # True
    # list是否可迭代
    print(isinstance([1,2,3], Iterable))  # True
    # 整数是否可迭代
    print(isinstance(123, Iterable))  # False
    

    1.2 迭代器

    现在已经有很多对象可以使用for循环,而且相对于其他语言,pythonfor循环的使用方式非常优雅,简洁和便利

    for`循环的背后就是迭代器

    迭代器使用遍及python,并且使用方式统一

    但凡是返回一个迭代器的对象,都可以成为可迭代对象。比如range对象。


    1.3 迭代器的工作原理

    使用迭代器的步骤简述如下:

    1. 调用内置函数iter(container), 把容器作为参数传递进去,返回一个对象,这个对象就是一个迭代器对象。容器对象就是咱们前边说的str,list
    2. 迭代器对象中有一个方法__next()__,这个方法每调用一次,就可以访问到容器中的一个元素,我们自己要调用的话,只需要调用内置函数next(it)就可以了
    3. 当容器中最后一个元素被迭代后, 再调用__next()__方法, 则会抛出一个StopIteration异常, for循环捕捉到这个异常后就可以终止循环了.

    当运行代码:

    list1 = [1, 2, 3]
    for x in list1:
      ....
    

    实际执行的情况是

    1.3 使用迭代器访问字符串中的元素

    s = "acdefgh"
    
    # 获取字符串 s 的迭代器, 其实等价于 it = s.__iter__()
    it = iter(s)
    
    print(next(it))# 迭代第一个元素
    print(next(it))
    print(next(it))
    print(next(it))
    print(next(it))
    

    1.4 使用迭代器访问列表中的元素

    s = [10, 30, 40, 20, 2]
    it = iter(s)
    print(next(it))		# 10
    print(next(it))		# 30
    print(next(it))		# 40
    

    二、生成器

    生成器算的上是python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,不过这种迭代器更加优雅。他只需要一个yield关键字。生成器一定是迭代器(反之不成立),因此任何生成器也是以一种懒加载的模式生成值。

    generator(生成器)是一个简单且强大的创建迭代器的工具

    生成器除了使用yield之外, 就像一个正常的函数, 想在任何地方返回数据, 只需要添加yield就可以了.

    我们调用next()函数, 一旦碰到yield则返回yield后的数据, python 并且可以保存当前的状态和位置, 下次再调用next(), 则继续从此处执行.

    # 生成能够迭代整数 1-n 的迭代器函数.  调用这个方法, 方法内的代码并不会立即执行, 而是返回一个生成器对象
    def foo(n):
        for i in range(1, n):
            yield i  # 每次碰到 yield, 则在此暂停, 并保存这个位置
    
    
    for i in foo(20):
        print(i)
    

    当然也可以使用下面的方式去使用生成器函数

    def foo(n):
        for i in range(1, n):
            yield i  # 每次碰到 yield, 则在此暂停, 并保存这个位置
    
    
    it = foo(20)
    
    print(next(it))
    print(next(it))
    

    1.2.1 生成器表达式

    生成器表达式(Generator Expressions), 是一个对象, 他执行的结果和以前学习的列表推导类似, 但会迭代的生成结果.

    他的语法也与列表类似, 只是需要把以前的[]换成()

    语法:

    it = (express for item in iterator)
    
    def foo(n):
        for i in range(1, n + 1):
            yield i
    
    # foo(20)返回的迭代器生成一个新的迭代器
    it = (x * x for x in foo(20))
    
    for y in it:
        print(y)
    

    1.2.2 生成器表达式和列表的差异

    从写法上来看,生成器表达式使用(), 而列表用[]. 但是他们之间还是有很重要的差异.

    他们的主要区别在于其中的元素(数据)的生成时间不同!

    1. 列表创建成功之后, 那么他里面的元素也已经创建成功, 而且是实实在在的占据着内存! 也就是说, 从物理上来看他们已经存在了.
    2. 而生成器表达式不一样, 仅仅是创建了一个生成器而已, 那些元素还没有创建. 只有当你使用for或者next()的时候才会根据需要来创建元素.
    3. 所以, 生成器不可能有添加, 删除等这些方法.
    4. 如果数据量比较大的时候, 使用生成器表达式的性能要好于列表.
    5. 列表推倒只能生成列表, 而生成器表达式可以根据需要生成任何类型的序列.
  • 相关阅读:
    Spring(7)AOP的相关概念(二)
    Spring(6)AOP的相关概念(一)
    Spring(5)基于注解的IOC配置
    Spring(4)使用 Spring的IoC的实现增删该查
    Spring(3)使用 spring 的IOC解决程序耦合
    Oracle体系结构概述(一)
    Spring(2) IoC 的概念和作用
    Spring(1)Spring概述
    Mybaits(15)注解开发
    Mybaits(14)存储过程
  • 原文地址:https://www.cnblogs.com/yanadoude/p/12619076.html
Copyright © 2011-2022 走看看