转载请注明出处:https://www.jianshu.com/u/5e6f798c903a

[^*] 表示注脚,在文末可以查看对应连接,但简书不支持该语法。

首先,容器和 iterable 间没有必然的关联性。对象可以是非 iterable 的容器,也可以是非容器的 iterable (如,文件对象和套接字对象)。另外,容器通常是有限的,而 iterable 可以表示一个无限的数据源。

有关容器的介绍可查看我另一篇文章:如何理解Python中的容器对象

iterable 在官方文档的语境中存在如下两种含义:

第一种是特指实现了 __iter__ 方法的对象[^2],本节后续部分会将此类对象称作 IterableObjc。

Tips:Iterator 和 Generator 均属于 IterableObjc。

from collections import abc

class IterableObjc:

def __iter__(self):

cont = 0

while cont < 3:

cont += 1

yield cont

a_iterable = IterableObjc()

assert isinstance(a_iterable, abc.Iterable) # 无异常

第二种将 iterable 视作一种抽象概念。只要内置函数 iter() [^5]可接受的对象,均被视作 iterable (这里特指 iter() 的单参数形式,不含第二参数)。因此,只要定义了 __iter__() 或 __getitem__() 中的任意一个,便可被认定为 iterable。但是,只定义了 __getitem__() 的对象,并不是 IterableObjc。可见,第二种含义所含对象的范围大于第一种含义,可认为 IterableObjc 是 iterable 的子集。

本节后续部分提及的 iterable 均采用第二种含义。

class GetitemObjc:

def __getitem__(self, item):

cont = 0

while cont <= item:

cont += 1

if cont >= 5:

raise StopIteration()

return cont

a_getitem = GetitemObjc()

assert isinstance(a_getitem, abc.Iterable) # 异常

1. iterable 与 for 循环

将 iterable 用于 for 循环时,我们不需要自己调用iter() ,也不需要自己处理迭代器对象。for 语句会在循环期间,自动创建一个用于保存迭代器的临时无名变量。通过反汇编(disassemble),可以让我们更加直观的了解 for 循环的执行过程,代码如下:

dis.dis("for _ in iterable: pass")

输出:

1 0 SETUP_LOOP 12 (to 14)

2 LOAD_NAME 0 (iterable)

4 GET_ITER

>> 6 FOR_ITER 4 (to 12)

8 STORE_NAME 1 (_)

10 JUMP_ABSOLUTE 6

>> 12 POP_BLOCK

>> 14 LOAD_CONST 0 (None)

16 RETURN_VALUE

通过观察输出,可见解释器会显式调用 GET_ITER,这相当于调用了 iter(iterable) 。也就是说for 语句会自动调用 iter(iterable),从而将 iterable 对象转换为一个迭代器[^6]。以便能够通过 FOR_ITER 指令 (相当于 next() 方法) 获取下一个元素。注意:无法直接从字节码指令中观察到全部过程,因为解释器对此进行了优化。

2. iterable 与内置函数

iterable 还可用于任何需要顺序对象的地方,比如内置函数:

any(iterable)

class list([iterable])

map(function, iterable, ...)

….

对内置函数来说,其 iterable 参数仍采用第二种含义,绝非严格意义上的 IterableObjc。

比如文档中对内置函数 any(iterable) 的解释如下:

如果可迭代(iterable)对象中某个元素的布尔值为 True,则返回 True 。如果可迭代对象为空,则返回 False 。相当于如下代码:

def any(iterable):

for element in iterable:

if element:

return True

return False

由此可以推测,如果内置函数带有 iterable 参数,则会先将 iterable 转换为迭代器,然后再进行处理。在内置函数内部可以通过 for 循环间接转换,也可直接使用 iter() 进行转换(注意,内置函数是 C 实现,这里段文字仅是为了给出一种思路)

3. IterableObjc 与 __iter__

首先明确两个概念:

IterableObjc :所有实现了 __iter__ 的对象均可称作 IterableObjc

迭代器:是指同时实现了 __iter__ 和 __next__ 的对象,迭代器也属于 IterableObjc。

从本质上来说, __iter__ 方法就是为了返回迭代器而存在的,当需要容器提供迭代器时,便会调用此方法。但由于 IterableObjc 本身也可能是迭代器,所以便产生了以下两种情形:

# 第一种情况:IterableObjc本身不是迭代器

class IterableObjc:

"""

在这种情况下,每次调用__iter__方法时,

都会返回一个具备新id的迭代器对象,不会返回实例本身。

"""

def __iter__(self):

"""调用该生成器函数,便会返回一个迭代器"""

cont = 0

while cont < 3:

cont += 1

yield cont

# 第二种情况:IterableObjc本身就是迭代器

class IteratorObjc:

"""

在这种情况下,每次调用__iter__方法时,

会返回实例对象自身,不会创建具备新id的迭代器对象。

"""

def __iter__(self):

self._count = 0

# 调用时返回实例自身

return self

def __next__(self):

while self._count < 3:

self._count += 1

return self._count

python iterable对象_如何理解Python中的iterable对象相关推荐

  1. python参数传递方法_深入理解python中函数传递参数是值传递还是引用传递

    python 的 深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是&q ...

  2. python赋值语句对错_深入理解Python中变量赋值的问题

    前言 在Python中变量名规则与其他大多数高级语言一样,都是受C语言影响的,另外变量名是大小写敏感的. Python是动态类型语言,也就是说不需要预先声明变量类型,变量的类型和值在赋值那一刻被初始化 ...

  3. python ioc框架_轻松理解 Spring 中的 IOC

    Spring 简介 Spring 是一个开源的轻量级的企业级框架,其核心是反转控制 (IoC) 和面向切面 (AOP) 的容器框架.我们可以把 Spring 看成是对象的容器,容器中可以包含很多对象, ...

  4. python语句解释_深入理解python with 语句

    深入理解python with 语句 python中with 语句作为try/finally 编码范式的一种替代, 适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的" ...

  5. 什么是python装饰器_深入理解 Python 装饰器

    作者简介 曾凡伟,携程信息安全部高级安全工程师,2015年加入携程,主要负责安全自动化产品的设计和研发,包括各类扫描器.漏洞管理平台.安全 SaaS 平台等. Python 是一门追求优雅编程的语言, ...

  6. python sorted原理_深入理解Python的sorted

    1. 简介 sorted的派排序功能真强大,从前一直使用C++.Java以为其功能很强大了,但与Python一比,真的要差一些. 2. 函数定义 sorted(iterable, cmp=None, ...

  7. 深入理解python异步编程_深入理解Python异步编程

    1 什么是异步编程 1.1 阻塞程序未得到所需计算资源时被挂起的状态. 程序在等待某个操作完成期间,自身无法继续干别的事情,则称该程序在该操作上是阻塞的. 常见的阻塞形式有:网络I/O阻塞.磁盘I/O ...

  8. 完全理解python迭代对象_完全理解Python迭代对象、迭代器、生成器

    1.assert:python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触 ...

  9. python select模块_深入理解python中的select模块

    简介 Python中的select模块专注于I/O多路复用,提供了select  poll  epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kque ...

最新文章

  1. 教你用OpenCV人脸检测自动给头像戴圣诞帽(附代码)
  2. 新的ipad,用xcode编译报错 dyld_shared_cache_extract_dylibs
  3. 搞事情?!2020云·创季来啦,量子位带你领略云产业的耳目一新!
  4. 树莓派使用python+继电器控制220V灯泡
  5. 在新版CSDN博客添加友情链接
  6. 如何构建大数据分析平台
  7. jquery效果插件网址
  8. nsis打包php项目加环境,NSIS制作安装文件全攻略(一) zz
  9. 国外大牛开发者创造出Siri第三方服务器
  10. Centos7下ping通ip但是ping不通域名+firefox无法打开网页
  11. kworker内核工作队列详解
  12. ubunut18.04 pycharm创建快捷方式和右键创建空白文件夹
  13. python实现华氏温度和摄氏温度转换
  14. JUC:6_1集合类并发问题、集合类并发不安全解决方案1:list
  15. MySQL 删除大量数据
  16. win10解决设置默认打开方式不生效问题
  17. mac php7 mysql.so_[安装] mac安装PHP7经历
  18. 成交量、持仓量与价格运动的关系
  19. Mysql免安装版下载以及配置
  20. 湘潭市古城中学《西游记》手抄报活动作品展示

热门文章

  1. 每秒处理1000万用户请求…云上架构如何实现高性能和高可用
  2. 经典案例:如何优化Oracle使用DBlink的SQL语句
  3. 【华为云技术分享】机器学习(01)——机器学习简介
  4. 装13失败后,我决定使用Python为生僻字批量注音
  5. 细数MQ那些不得不说的8大好处
  6. MapReduce高级编程2
  7. Android笔记 隐式意图vs显示意图+隐式意图打开短信应用demo
  8. MATLAB学习笔记——二维和三维绘图
  9. java表达式的类型_java – 此表达式的目标类型必须是功能界面
  10. java.sql.connection 长时间不使用_车子长时间停放不使用,要做到这几点!不然报废是小,安全是大...