前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python迭代器与解析

python迭代器与解析

作者头像
tnt阿信
发布2020-08-05 10:07:16
3610
发布2020-08-05 10:07:16
举报

python迭代器与解析

迭代器初探

可能大家都已经知道for循环语句可以作用域任何序列类型,包括列表、元组以及字符串。实际上for循环能够作用于任何可迭代的对象,除了for语句,python中所有会从左至右的迭代工具都是如此,这些迭代工具包括:for循环、列表解析、in成员关系测试以及map内置函数等….

这里就涉及到很重要的一个概念-----可迭代对象,除此之外还有一个与它很类似的概念,叫做迭代对象,很多人经常分不清楚他们。迭代对象是指实现了__iter__next方法的对象,而可迭代对象可以只实现__iter__方法,也可以两个都实现。有的可迭代对象的迭代对象就是它本身。说了那么多,不如我们直接自己实现一下:

代码语言:javascript
复制
class MyRange(object):
    def __init__(self, n):
        self.idx = 0
        self.n = n
    def __iter__(self):
        return self
    def next(self):
        if self.idx < self.n:
            val = self.idx
            self.idx += 1
            return val
        else:
            raise StopIteration()

上面这个类既实现了__iter__方法,也实现了next方法,并且它的__iter__方法返回了它自身,所以这个可迭代对象的的迭代对象就是它自身。上面的类其实就相当于我们python中使用的xrange函数。

代码语言:javascript
复制
myRange = MyRange(3)
for i in myRange:
    print i 

这里写图片描述

如果一个可迭代对象同时它的迭代对象又是它本身的话会导致一个问题,无法重复迭代,例如:

从图中可以看到,当我迭代完一次过后,迭代器就被迭代完了,当我第二次用for迭代的时候没有任何输出。解决这一问题的办法就是分离迭代对象与可迭代对象。

代码语言:javascript
复制
class Zrange:
    def __init__(self, n):
        self.n = n
    def __iter__(self):
        return ZrangeIterator(self.n)
class ZrangeIterator:
    def __init__(self, n):
        self.i = 0
        self.n = n
    def __iter__(self):
        return self
    def next(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()    
zrange = Zrange(3)
print zrange is iter(zrange)         
print [i for i in zrange]
print [i for i in zrange]

结果:

这里写图片描述

注:我们可以通过iter()内建函数获取一个可迭代对象的迭代对象,然后通过is比较,例如:

这里写图片描述 可以看到列表类型的迭代对象不是它本身

手动迭代:iter与next

相信通过上面的例子,大家已经很清楚迭代器的工作原理了,下面我们来通过手动迭代,更加直观的来认识迭代器。

查看大图可以看到,我们创建了一个a列表,这个列表中实现了__iter__方法,我们已经知道这个方法返回了一个迭代对象,我们接着看一下

这里写图片描述

可以看到这个迭代对象中实现了next方法。

这里写图片描述

然后我们通过手动迭代观察了一下,每调用一次next迭代器就走一步,走到头就抛出StopIteration。我们的for循环等迭代操作也就是利用了这个原理。

注:文件也是一个可迭代对象,我们可以用for循环按行遍历

列表解析初探

我们用一个例子走近列表解析的大门,加入我们想要修改一个列表,以前我们能会这么做:

代码语言:javascript
复制
L = [1,2,3,4,5]
for i in range(len(L)):
    L[i] += 10
print L

但是实际上这样太麻烦了,我们完全可以偷懒,而且还可以提高运行效率(通常列表解析效率更高):

代码语言:javascript
复制
L = [x+10 for x in L]
print L

现在让我们来更详细的剖析一下这个例子: 列表解析写在一个方括号中,因为他们最终是构建一个新的列表(python3.0中,可以用解析构造元组,字典等)。上面的列表解析式执行的操作就是,依次从原来的L列表中取出一个数,暂存在x变量里,然后这个x在加上10,直到遍历完整个L表,同时也就形成了一个新的列表。 再来看一个例子:

代码语言:javascript
复制
a = ['123\n','234\n']
b = [x.strip() for x in a]
print b

这里写图片描述

我们对原来列表中的每一项去掉了换行符,然后组成了新的列表

生成器

刚刚我们也了解了列表解析式是什么东西,其实生成器的写法与列表解析式差不多,只是把方括号改为圆括号。例如:

代码语言:javascript
复制
a = (x for x in range(11))

这就构造了一个生成器。

这里写图片描述

那到底生成器是什么东西?它有什么用呢? 我们通常在写列表解析式的时候,都是表达式执行过后都会直接生成一个序列,比如:

代码语言:javascript
复制
a = [x for x in range(11)]

就会生成

代码语言:javascript
复制
[1,2,3,4,5,6,7,8,9,10]

这样一个完整的序列,但是生成器表达式执行后生成的不是一个序列,而是相当于一种算法,每运行一次这个表达式都会返回序列的下一个值,这个值是现场生成的(不是一开始就保存在内存中的)。这样有什么好处,相信大家都可以想到——节约空间(也许小程序中感受不到有什么差异,但是当这个序列很大的时候就…..) 实际上,生成器生成的是一个迭代对象也是一个可迭代对象。所以,其实它也有一个next方法:

这里写图片描述

当然,这种写法构造的生成器,实际上它能完成的功能不丰富,就像一个列表解析式一样。所以,还有另外一种写法,例如:

代码语言:javascript
复制
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print b
        a, b = b, a + b
        n = n + 1

上面的函数执行后会打印一串斐波那契数列。我们同样可以写成一个生成器,这只需要简单的把print改为yield。

代码语言:javascript
复制
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

有了yield之后,每调用一次next方法,就会返回yield后面的值,并且不再往后执行,而是在下一次调用next方法时执行,一直重复,直到抛出StopIteration错误。

send与close方法

这两个方法也是与生成器相关的,但是感觉用的不太多,就不详细介绍了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 一个安全研究员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • python迭代器与解析
    • 迭代器初探
      • 手动迭代:iter与next
        • 列表解析初探
          • 生成器
            • send与close方法
            相关产品与服务
            云开发 CloudBase
            云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档