前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python的for循环,背后是什么原理?

python的for循环,背后是什么原理?

原创
作者头像
zero000
修改2021-05-31 20:37:24
1.2K0
修改2021-05-31 20:37:24
举报
文章被收录于专栏:程序员菜谱程序员菜谱
python iterators
python iterators

一、什么是 iterators(迭代器)?

大部分可以使用for关键字遍历的container都是iterator

代码语言:txt
复制
for element in [1, 2, 3]:
    print(element)
for element in (1, 2, 3):
    print(element)
for key in {'one':1, 'two':2}:
    print(key)
for char in "123":
    print(char)
for line in open("myfile.txt"):
    print(line, end='')

这种访问方式清晰、简洁、方便。

其背后的原理是,for 语句对容器对象调用 iter()。该函数返回一个迭代器对象,该对象定义了 __next__() 方法,该方法一次访问一个容器中的元素。当没有更多元素时,__next__() 会引发一个 StopIteration 异常,它告诉 for 循环终止.

可以使用内置函数 next() 调用 __next__() 方法

代码语言:txt
复制
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    next(it)
StopIteration

二、如何构造和调用 iterators?

对类添加 iterator 的行为,可以通过在类中定义 __iter__() 方法实现,该方法返回一个包含 __next__() 的对象;如果类已经定义 __next__()__iter__() 可以返回 self

代码语言:txt
复制
class Reverse:
    """Iterator for looping over a sequence backwards."""
    def __init__(self, data):
        self.data = data
        self.index = len(data)

    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]
代码语言:txt
复制
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
...     print(char)
...
m
a
p
s

三、iterators 常用于哪些场景?

Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。

根据这个特点,我们知道iterator可以表示一些无限大的序列,例如Fibonacci(斐波那契)数列,所有的质数。

注意:listdictstr 等数据类型不是 Iterator,但可以通过 iter(obj) 转换成一个对象

代码语言:txt
复制
>>> from collections.abc import Iterable
>>> isinstance([], Iterable)
True
代码语言:txt
复制
>>> from collections.abc import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True

四、iterators 实战

代理迭代

问题

你构建了一个自定义容器对象,里面包含有列表、元组或其他可迭代对象。 你想直接在你的这个新容器对象上执行迭代操作。

解决方案

代码语言:txt
复制
class Node:
    def __init__(self, value):
        self._value = value
        self._children = []

    def __repr__(self):
        return 'Node({!r})'.format(self._value)

    def add_child(self, node):
        self._children.append(node)

    def __iter__(self):
        return iter(self._children)

# Example
if __name__ == '__main__':
    root = Node(0)
    child1 = Node(1)
    child2 = Node(2)
    root.add_child(child1)
    root.add_child(child2)
    # Outputs Node(1), Node(2)
    for ch in root:
        print(ch)

实现迭代器协议

通过迭代实现深度优先遍历

代码语言:txt
复制
class Node:
    def __init__(self, value):
        self._value = value
        self._children = []

    def __repr__(self):
        return 'Node({!r})'.format(self._value)

    def add_child(self, node):
        self._children.append(node)

    def __iter__(self):
        return iter(self._children)

    def depth_first(self):
        yield self
        for c in self:
            yield from c.depth_first()

# Example
if __name__ == '__main__':
    root = Node(0)
    child1 = Node(1)
    child2 = Node(2)
    root.add_child(child1)
    root.add_child(child2)
    child1.add_child(Node(3))
    child1.add_child(Node(4))
    child2.add_child(Node(5))

    for ch in root.depth_first():
        print(ch)
    # Outputs Node(0), Node(1), Node(3), Node(4), Node(2), Node(5)

在这段代码中,depth_first() 方法简单直观。 它首先返回自己本身并迭代每一个子节点并 通过调用子节点的 depth_first() 方法(使用 yield from 语句)返回对应元素。

参考

  1. https://docs.python.org/3/tutorial/classes.html#iterators
  2. https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640
  3. https://python3-cookbook.readthedocs.io/zh_CN/latest/c04/p02_delegating_iteration.html

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是 iterators(迭代器)?
  • 二、如何构造和调用 iterators?
  • 三、iterators 常用于哪些场景?
  • 四、iterators 实战
    • 代理迭代
      • 问题
        • 解决方案
          • 实现迭代器协议
          • 参考
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档