zoukankan      html  css  js  c++  java
  • Python 学习 第六篇:迭代和解析

    Python中的迭代是指按照元素的顺序逐个调用的过程,迭代概念包括:迭代协议、可迭代对象和迭代器三个概念。

    迭代协议是指有__next__()函数的对象会前进到下一个结果,而到达系列的末尾时,则会引发StopIteration异常。为了支持迭代协议,Python内置了两个函数:iter()和next()函数。iter()从可迭代对象中获得一个迭代器,迭代器含有next()函数。next()函数的作用就是调用对象的__next__()函数,从而递进进到下一项。

    在Python中,任何支持迭代协议的对象都是可迭代的。如果对象是序列类型,或者在迭代工具中一次产生一个结果,那么就是可迭代的,这就以为着,序列(字符串、元组和列表)是可迭代对象。

    迭代器是Python中实现迭代协议的对象,具体指的是iter()返回的,支持next()函数的对象。

    Python中的迭代工具会自动调用iter()和next()函数以实现迭代,迭代工具主要有:for循环、列表解析、in成员关系测试以及map内置函数等。

    一,手动迭代

    列表不是自身的迭代器,对于这样的可迭代对象,可以调用iter()函数来启动迭代,调用next()函数递进到下一项:

    >>> a=list(range(0,5))
    >>> a is iter(a)
    False
    >>> a=iter(a)
    >>> next(a)
    0

    像for循环等迭代工具,会自动调用iter()和next()函数,以实现序列的自动迭代:

    >>> for i in range(0,5): print(i,end=' ')
    0 1 2 3 4 

    二,生成器

    生产器是一个延迟产生结果的工具,在需要的时候才产生结果,而不是立即产生结果。

    1,生成器函数

    Python提供了yield语句以实现生成器函数,以实现在需要的时候才产生结果,而不是立即产生结果。Python的生产器函数是指:编写为常规的def语句,但是使用yield语句,一次返回一个结果,在每个结果之间挂起和继续的状态。 

    生产器函数自动实现迭代协议,每次调用只返回一个值,下次调用时,会从其退出的地方继续执行。

    生产器函数和常规函数的不同之处在于:生产器yield一个值,而不是return一个值。yield语句挂起该函数,并向调用者发送一个值,但是,保留足够的状态以使得函数能够从它离开的地方继续执行。当继续时,函数在上一个yield返回后继续执行。这使得生产器函数每次调用只返回一个值,穷尽调用会产生一系列的值。

    >>> def seq_int(n):
        for i in range(n):
            yield i**2
        
    >>> for i in seq_int(5):
        print(i,end =' ')
      
    0 1 4 9 16 

    生产器函数返回的对象就是迭代器,可以使用next()前进到下一项:

    >>> func=seq_int(5)
    >>> iter(func) is func
    True
    >>> next(func)
    0

    2,生产器表达式

    另外一个实现生产器的对象是生产器表达式,从语法上讲,生成器表达式是在小括号中的表达式。从执行过程来讲,生产器表达式不在内存中构建结果,而是返回一个生成器对象,这个对象支持迭代协议。

    >>> a=(x**2 for x in range(0,5))
    >>> a is iter(a)
    True

    三,解析

    解析分为列表解析,集合解析和字典解析。

    • 列表解析的格式是:[ f(x) for x in seq  ],对应的生成器表达式是:list( f(x) for x in seq )
    • 集合解析的格式是:{ f(x) for x in seq  },对应的生成器表达式是:set(f(x) for x in seq )
    • 字典解析的格式是:{key:value for (key, value) in zip(keys,values)},对应的生成器表达式是:dict((x,f(x))  for x in items  )

    从语法上讲,列表解析是在中括号中的表达式;从执行过程来讲,列表解析对序列中的每一个元素执行一个操作;从执行的结果来讲,列表解析产生的一个新的列表对象。

    由于列表解析产生的结果是一个列表对象,包含所有的序列项,不属于延迟产生结果的工具。

    >>> a=[x**2 for x in range(0,5)]
    >>> isinstance(a,list)
    True

    四,内置的迭代器函数

    这一节,总结Python 3.0中内置的迭代器函数,除了range()函数之外,其余的函数都会产生迭代器对象,延迟产生结果。

    1,range 迭代对象

    range返回一个可迭代对象,该迭代对象根据需要产生范围中的数字,而不是在内存中构建一个列表。如果需要一个范围列表的话,必须使用list( range(...))来强制返回一个列表。

    >>> r = range(0,5)
    >>> iter(r) is r
    False
    >>> list(r)
    [0, 1, 2, 3, 4]
    >>> r=iter(r)
    >>> next(r)
    0

    2,zip实现并行遍历

    zip()函数用于合并序列,按照序列中元素的位置,把序列的元素组合成元组,元组项的数量就是zip合并的序列的个数。当序列的长度不同时,zip会以最短序列的长度为准来截断所得到的元组。

    例如,zip把序列a和b合并为一个序列c,c的元素的元组(0,5),(1,6),(2,7),(3,8),(4,9)。

    >>> a = range(0,5)
    >>> b = range(5,10)
    >>> c = zip(a,b)
    >>> iter(c) is c
    True
    >>> next(c)
    (0, 5)
    >>> list(c)
    [(1, 6), (2, 7), (3, 8), (4, 9)]

    3,map对序列应用函数

    map()函数对一个序列的各个元素应用函数,返回函数调用的结果序列。

    >>> m=map(ord,'abcd')
    >>> iter(m) is m
    True
    >>> list(m)
    [97, 98, 99, 100]

    4,产生偏移和元素

    enumerate是Python内置的函数,作用于每一个序列项,获取每一个序列项偏移,并把偏移和序列项组合成元组(index, item)返回。原始序列的每个元素及其索引都能得到。

    enumerate()函数返回一个迭代器对象,使用next()方法会返回下一个元素:

    >>> t=enumerate('abcd')
    >>> iter(t) is t
    True
    >>> list(t)
    [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

    在for循环结构中,每次迭代,for循环都会自动调用next()函数以返回下一个元组(index,item):

    >>> [c * i for (i,c) in enumerate('abcd')]
    ['', 'b', 'cc', 'ddd']

    5,filter迭代器

    filter()函数对一个序列的各个元素应用函数,返回结果为True的元素。

    >>> f=filter(bool, ['a','','b',None])
    >>> iter(f) is f
    True
    >>> list(f)
    ['a', 'b']

    6,reduce() 函数

    注意:reduce()函数并不是一个迭代器,它是functools模块中的一个工具函数。

    reduce()用于对序列的元素依次应用函数,并把函数调用的结果作为参数传递给函数,最终返回函数调用的结果。

    >>> from functools import reduce
    >>> reduce((lambda x,y:x+y),range(0,5))
    10

    reduce()函数执行流程等价于下面的代码块:

    x=list(range(0,5)]
    res=x[0]
    for i in x[1:] :
        res+=i

    参考文档:

  • 相关阅读:
    IIS 无法下载EXE
    大数据ListView
    vss error reading from file
    fatal error LNK1107
    A Generic Singleton Class
    转 ORACLE 的FOR循环、游标、时间值函数、转换函数题目
    regsvr32.exe 会用
    MSChat 临时目录
    关于LinkedList的三种写法的效率
    旋转门压缩算法
  • 原文地址:https://www.cnblogs.com/ljhdo/p/10104824.html
Copyright © 2011-2022 走看看