Python-for循环的内部机制

作者:monte 时间:2023-02-02 20:47:18 

Python中,使用for循环可以迭代容器对象中的元素,这里容器对象包括是列表(list)、元组(tuple)、字典(dict)、集合(set)等。但是,为什么这些对象可以使用for循环进行操作呢?

首先,定义一个简单的类尝试一下:


class TestRange:
 def __init__(self, num):
   self.num = num
for i in TestRange(10):
 print(i)

# 输出
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'TestRange' object is not iterable

错误信息提示,'TestRange' object 不是可迭代的对象。那么,什么才是可迭代的对象呢?

在可迭代的对象中,需要实现一个__iter__魔法方法,而且这个方法的返回值需要是一个迭代器。那么,什么是迭代器呢?

迭代器只需要实现__next__魔法方法。

以列表(list)为例:


>>> nums = [13,12,33]
>>> iter_ret = nums.__iter__() # x有此方法,说明list是可迭代的,而且该方法返回一个迭代器
>>> iter_ret
<list_iterator object at 0x100f32198>

>>> iter_ret.__next__()
13
>>> iter_ret.__next__()
12
>>> iter_ret.__next__()
33
>>> iter_ret.__next__()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

分析:

如上所示,列表nums中实现了__iter__方法,而且返回一个迭代器(iterator),迭代器中实现了__next__方法。在不断调用__next__的过程中,就是在不断返回nums中的元素,直到出现StopIteration的错误。

其实,for语句的作用与此类似。for语句的内部机制为

  • 先判断对象是否为可迭代对象,即是否存在__iter__方法,如果存在则调用__iter__方法,返回一个迭代器;否则,直接抛出TypeError异常;

  • 不断地调用迭代器的__next__方法,每次调用按顺序迭代获取当前的值;

  • 迭代完所有元素,就抛出异常 StopIteration,这个异常 python 解释器自己会处理;

前面的 TestRange 报错是因为它没有实现迭代器协议里面的这两个方法,现在继续改进:


class TestRange:
 def __init__(self, _max):
   self.i = 0
   self._max = _max

def __iter__(self):
   return self

def __next__(self):
   if self.i < self._max:
     i = self.i
     self.i += 1
     return i
   else:
     # 达到停止条件时,抛出此异常
     raise StopIteration()

# 进行测试
for i in TestRange(3):
 print(i)
# 输出
0
1
2

分析:

因为这个类中,已经实现了__next__方法,所以基于这个类所创建的对象,本身就是一个迭代器。又因为可迭代对象需要有__iter__方法,而且返回一个迭代器,所以__iter__返回对象本身self即可。

来源:https://segmentfault.com/a/1190000022911784

标签:python,for,循环
0
投稿

猜你喜欢

  • Python cookbook(数据结构与算法)让字典保持有序的方法

    2022-04-28 03:28:04
  • python中pymysql的executemany使用方式

    2024-01-12 14:35:46
  • Python3+selenium实现cookie免密登录的示例代码

    2023-01-31 15:43:09
  • 在Python中通过threshold创建mask方式

    2022-10-22 16:52:49
  • Spring Data JPA的Audit功能审计数据库的变更

    2024-01-21 18:30:29
  • 请注意页面head区域的编码是不是规范

    2008-08-06 13:14:00
  • Web标准基础教程:CSS简写指南

    2010-04-02 12:47:00
  • 基于python的多进程共享变量正确打开方式

    2022-02-12 10:30:53
  • Django模板导入母版继承和自定义返回Html片段过程解析

    2023-06-16 21:13:38
  • php 运算符与表达式详细介绍

    2024-05-13 09:53:23
  • 窥探jQuery——面向JavaScript程序员

    2008-06-17 14:35:00
  • 基于Python绘制一个摸鱼倒计时界面

    2022-09-02 03:03:26
  • python的numpy模块安装不成功简单解决方法总结

    2022-10-23 18:33:15
  • Python获取电脑硬件信息及状态的实现方法

    2023-01-23 21:24:15
  • node.js中的fs.realpathSync方法使用说明

    2024-05-13 09:59:04
  • python单元测试框架pytest的使用示例

    2023-01-20 05:59:27
  • SQL Server 安装出错:以前的某个程序安装已在安装计算机上创建挂起的文件操作

    2010-02-23 14:48:00
  • golang copy函数使用的坑

    2023-07-09 19:53:44
  • python xlsxwriter创建excel图表的方法

    2021-01-12 03:16:10
  • Python Celery异步任务队列使用方法解析

    2023-05-18 02:34:53
  • asp之家 网络编程 m.aspxhome.com