Python 迭代过程浅析

本文详细探讨了Python迭代过程,包括迭代上下文、简化和严格的内部步骤,以及如何构造可迭代对象。通过示例展示了`iter`和`next`函数在迭代中的作用,并解释了Python的'新式类'在迭代中的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python 迭代过程浅析

mywang88

2019-07-17

简介

本文尝试浅析 Python 的迭代上下文的内部过程。

Python 版本为 3.7 。

示例

迭代上下文

Python 中最常见的迭代上下文是 for 循环语句:

for i in a:
	print(i)

如果这段代码能够正常执行,我们就说对象 a 是可迭代的,即 Iterable

更为严格的说法是,((变量 a 所引用的对象)所属于的类)的实例对象是可迭代的,括号用来帮助断句。

简化的内部过程

为了更好地理解迭代过程,参考下列代码:

b = iter(a)
while True:
	try:
		i = next(b)
		print(i)
	except StopIteration:
		break

主要步骤:

  1. a 传递给内置函数 iter ,得到返回值 b
  2. 迭代开始。
  3. b 传递给内置函数 next ,得到返回值,赋值给循环变量 i
  4. 执行循环体语句,此处为 print(i)
  5. 重复步骤2 3,直到 next 函数抛出 StopIteration 异常。
  6. 迭代结束。

内置函数 iter 会调用 a__iter__ 方法,内置函数 next 会调用 b__next__ 方法。

不难发现,对象 a__iter__ 方法,以及对象 b__next__ 方法是一个对象可以被用来迭代的关键,而迭代过程的具体逻辑也由这两个方法定义。

需要补充的是,在 2.2 之后的 Python 版本中,应用了“新式类”的概念。在内置运算的上下文中,对一个对象的内置属性的引用,会跳过该对象本身的命名空间,直接在对象所属于的类(继承树)中进行查找。

构造可迭代对象

依据上一节的描述,我们可以自己构造一个可迭代对象:

class B:
    def __next__(self):
        return 'Still me'

class A:
    def __iter__(self):
        return B()
    
a = A()
for i in a:
    print(i)

运行代码将不断打印 Still me

更简化的形式:

class B:
    __next__ = lambda self: 'Still me'

class A:
    __iter__ = B

我们只需要满足 __iter____next__ 引用的对象是可调用的即可。

如果一个对象的 __iter__ 方法返回其本身,且定义了 __next__ 方法,那么它是一个“迭代器”对象。篇幅所限,本文只给出一个极简的示例:

class A:
    __iter__ = lambda self: self
    __next__ = lambda self: 'Still me'

本文中频繁使用 lambda 语句,是为了缩短篇幅,同时强调“可调用”这个概念。

更严格的内部过程

作为补充,给出以下示例:

b = a.__class__.__iter__(a)
while True:
	try:
		i = b.__class__.__next__(b)
		print(i)
	except StopIteration:
		break

当对象 a 被用来迭代时,Python 内部并不会以 a.__iter__ 的形式来引用对象 __iter__ 属性,而是调用内置函数 iter(a)

这样一来,无论对象 a 本身是否有定义 __iter__ 属性,Python 都会直接跳过它,去引用它所属于的类的 __iter__ 属性。如果 a 所属于的类没有定义 __iter__ 属性,Python 继续向上搜索类继承树,直到成功或失败。实际上,这正式 Python 的“新式类”的引用策略。

同理,对于 __next__ 属性,Python 执行相同的处理过程。

为了更好帮助理解,笔者画了一张示意图:
在这里插入图片描述
最后,需要补充的是,当 Python 无法 __iter____next__ 的机制来进行迭代的时候,会检查备选的 __getitem__ 方案,这不在本文的讨论范围内。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值