python iterable对象_如何理解Python中的iterable对象
转载请注明出处: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对象相关推荐
- python参数传递方法_深入理解python中函数传递参数是值传递还是引用传递
python 的 深入理解python中函数传递参数是值传递还是引用传递 目前网络上大部分博客的结论都是这样的: Python不允许程序员选择采用传值还是传 引用.Python参数传递采用的肯定是&q ...
- python赋值语句对错_深入理解Python中变量赋值的问题
前言 在Python中变量名规则与其他大多数高级语言一样,都是受C语言影响的,另外变量名是大小写敏感的. Python是动态类型语言,也就是说不需要预先声明变量类型,变量的类型和值在赋值那一刻被初始化 ...
- python ioc框架_轻松理解 Spring 中的 IOC
Spring 简介 Spring 是一个开源的轻量级的企业级框架,其核心是反转控制 (IoC) 和面向切面 (AOP) 的容器框架.我们可以把 Spring 看成是对象的容器,容器中可以包含很多对象, ...
- python语句解释_深入理解python with 语句
深入理解python with 语句 python中with 语句作为try/finally 编码范式的一种替代, 适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的" ...
- 什么是python装饰器_深入理解 Python 装饰器
作者简介 曾凡伟,携程信息安全部高级安全工程师,2015年加入携程,主要负责安全自动化产品的设计和研发,包括各类扫描器.漏洞管理平台.安全 SaaS 平台等. Python 是一门追求优雅编程的语言, ...
- python sorted原理_深入理解Python的sorted
1. 简介 sorted的派排序功能真强大,从前一直使用C++.Java以为其功能很强大了,但与Python一比,真的要差一些. 2. 函数定义 sorted(iterable, cmp=None, ...
- 深入理解python异步编程_深入理解Python异步编程
1 什么是异步编程 1.1 阻塞程序未得到所需计算资源时被挂起的状态. 程序在等待某个操作完成期间,自身无法继续干别的事情,则称该程序在该操作上是阻塞的. 常见的阻塞形式有:网络I/O阻塞.磁盘I/O ...
- 完全理解python迭代对象_完全理解Python迭代对象、迭代器、生成器
1.assert:python assert断言是声明其布尔值必须为真的判定,如果发生异常就说明表达示为假.可以理解assert断言语句为raise-if-not,用来测试表示式,其返回值为假,就会触 ...
- python select模块_深入理解python中的select模块
简介 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kque ...
最新文章
- 教你用OpenCV人脸检测自动给头像戴圣诞帽(附代码)
- 新的ipad,用xcode编译报错 dyld_shared_cache_extract_dylibs
- 搞事情?!2020云·创季来啦,量子位带你领略云产业的耳目一新!
- 树莓派使用python+继电器控制220V灯泡
- 在新版CSDN博客添加友情链接
- 如何构建大数据分析平台
- jquery效果插件网址
- nsis打包php项目加环境,NSIS制作安装文件全攻略(一) zz
- 国外大牛开发者创造出Siri第三方服务器
- Centos7下ping通ip但是ping不通域名+firefox无法打开网页
- kworker内核工作队列详解
- ubunut18.04 pycharm创建快捷方式和右键创建空白文件夹
- python实现华氏温度和摄氏温度转换
- JUC:6_1集合类并发问题、集合类并发不安全解决方案1:list
- MySQL 删除大量数据
- win10解决设置默认打开方式不生效问题
- mac php7 mysql.so_[安装] mac安装PHP7经历
- 成交量、持仓量与价格运动的关系
- Mysql免安装版下载以及配置
- 湘潭市古城中学《西游记》手抄报活动作品展示
热门文章
- 每秒处理1000万用户请求…云上架构如何实现高性能和高可用
- 经典案例:如何优化Oracle使用DBlink的SQL语句
- 【华为云技术分享】机器学习(01)——机器学习简介
- 装13失败后,我决定使用Python为生僻字批量注音
- 细数MQ那些不得不说的8大好处
- MapReduce高级编程2
- Android笔记 隐式意图vs显示意图+隐式意图打开短信应用demo
- MATLAB学习笔记——二维和三维绘图
- java表达式的类型_java – 此表达式的目标类型必须是功能界面
- java.sql.connection 长时间不使用_车子长时间停放不使用,要做到这几点!不然报废是小,安全是大...