python 中内置的可迭代的对象有 list、tuple、set、dict 等,那么我们自己怎么定义一个可迭代的对象呢?先来段代码吧

import re
import reprlib RE_WORD = re.compile('\w+') class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) def __getitem__(self, item):
return self.words[item] def __iter__(self):
for word in self.words:
yield word sen = Sentence("abc def 123 456")
for i in sen:
print(i) 运行这段代码,结果如下:
E:\python36\python3.exe E:/python_demo/test1.py
abc
def
123
456 Process finished with exit code 0`

通过结果分析,我们已经看出 Sentence 对象已经是可迭代的了!

此时我们可以注释掉 iter 函数

class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) def __getitem__(self, item):
return self.words[item] # def __iter__(self):
# for word in self.words:
# yield word 再次运行发现结果正常,接着注释 __getitem__ 函数
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) # def __getitem__(self, item):
# return self.words[item] # def __iter__(self):
# for word in self.words:
# yield word 发现报错了,报错信息很明朗,提示 Sentence 不是可迭代的对象
Traceback (most recent call last):
File "E:/python_demo/fluency_python/chapter14/test1.py", line 21, in <module>
for i in sen:
TypeError: 'Sentence' object is not iterable Process finished with exit code 1

看到这,是不是可以说,对象只需要实现 getitem 函数,那么该对象就是可迭代的呢?先别下定论,我们接着放开注释掉的 iter 函数

class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) # def __getitem__(self, item):
# return self.words[item] def __iter__(self):
for word in self.words:
yield word

发现运行结果又正确了,我们发现 __iter____getitem__ 中实现任意一个,对象就是可迭代的,怎么解释这种情况呢,Python 解释器中有这样的描述

解释器需要迭代对象 x 时, 会自动调用 iter(x)。

内置的 iter 函数有以下作用。

  1. 检查对象是否实现了 __iter__ 方法, 如果实现了就调用它, 获取一个迭代器。
  2. 如果没有实现 __iter__方法, 但是实现了 __getitem__ 方法,Python 会创建一个迭代器, 尝试按顺序(从索引 0 开始) 获取元素。
  3. 如果尝试失败, Python 抛出 TypeError 异常, 通常会提示“C object is not iterable”(C 对象不可迭代) , 其中 C 是目标对象所属的类。

    任何 Python 序列都可迭代的原因是, 它们都实现了 __getitem__ 函数。 其实, 标准的序列都实现了 __iter__ 函数, 因此你也应该这么做。
总结
  1. 因此我们在自定义可迭代对象需要实现__iter__函数
  2. 严格来讲,我们还需要实现 __getitem__ 函数,这个函数的主要作用是当前对象可通过下标取值

另外,如果有一个未知的对象,我们怎么判断该对象是否可迭代呢,两种方式:

  1. iter(x)

    这是最准确的判断方式,传入要判断的对象,只要对象实现了__getitem__ 、 __iter__中的其中一个,该对象都是可迭代的,否则抛出TypeError: 'C' object is not iterable 异常;这儿有个区别,如果仅仅实现了 getitem ,调用 iter(x) 返回的是迭代器对象,如果实现的是 iter ,那么调用 iter(x) 返回的是生成器对象;

  2. isinstance(x, abc.Iterable)

    该方式会自动忽略 getitem 函数,仅当对象实现了 iter 函数才返回 True,其他一律返回 False

原文链接:https://www.jianshu.com/p/048d40d86759

【转】Python中自定义可迭代对象的更多相关文章

  1. Python中的可迭代对象

      Python中的可迭代对象有:列表.元组.字典.字符串:常结合for循环使用: 判断一个对象是不是可迭代对象: from collections import Iterable isinstanc ...

  2. Python中的可迭代对象与迭代器对象

    刚刚学习Python,对“可迭代对象”和"迭代器对象"的个人理解,不知道对不对. 1.几个概念 (1)迭代工具:包括for循环.列表解析.in成员关系测试.....等等在内的,用于 ...

  3. Python中的可迭代对象/迭代器/For循环工作机制/生成器

    本文分成6个部分: 1.iterable iterator区别 2.iterable的工作机制 3.iterator的工作机制 4.for循环的工作机制 5.generator的原理 6.总结 1.i ...

  4. Python中的可迭代对象,迭代器与生成器

    先来看一张概览图,关于容器(container).可迭代对象(Iterable).迭代器(iterator).生成器(generator). 一.容器(container) 容器就是一个用来存储多个元 ...

  5. Python迭代器,可迭代对象,生成器

    迭代器 迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的界面,设计人员无需关心容器物件的内存分配的实现细节. ...

  6. Python Cookbook(第3版)中文版:15.20 处理C语言中的可迭代对象

    15.20 处理C语言中的可迭代对象¶ 问题¶ 你想写C扩展代码处理来自任何可迭代对象如列表.元组.文件或生成器中的元素. 解决方案¶ 下面是一个C扩展函数例子,演示了怎样处理可迭代对象中的元素: s ...

  7. 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】

    Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...

  8. Python:容器、迭代对象、迭代器、生成器及yield关键字

            在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...

  9. python中的一切皆对象

    python中一切皆对象是这个语言灵活的根本.函数和类也是对象,属于python的一等公民.包括代码包和模块也都是对象.python的面向对象更加彻底. 可以赋值给一个变量可以添加到集合对象中可以作为 ...

随机推荐

  1. Java高级程序设计笔记 • 【第5章 XML解析】

    全部章节   >>>> 本章目录 5.1 XML 文档概述 5.1.1 XML文档结构 5.1.1 XML结构说明 5.1.1 XML文档元素 5.1.2 XML文档语法规范 ...

  2. MongoDB 安装及制作成windows服务

    下载:  注:直接使用浏览器下载速度很慢,建议使用其他下载软件下载(比如:迅雷) 官网下载地址: https://fastdl.mongodb.org/win32/mongodb-win32-x86_ ...

  3. [服务器部署] Flask + virtualenv + uWSGI + Nginx 遇到的问题

    1.配置好了Flask + virtualenv +uWSGI,启动uWSGI并调试,网页显示 Internal Server Error 参考:https://www.cnblogs.com/cle ...

  4. Pandas系列(十七)-EDA(pandas-profiling)

    对于探索性数据分析来说,做数据分析前需要先看一下数据的总体概况,pandas_profiling工具可以快速预览数据. 安装 pip install pandas-profiling 使用 impor ...

  5. Itellij Idea使用

    图片如果损坏,点击链接查看 https://www.toutiao.com/i6491635946176381454/ 创建Maven项目 JDK环境 目前大多数IDE都没有集成JDK环境,IDEA也 ...

  6. Word2010制作倒福字

    原文: https://www.toutiao.com/i6489772955797553677/ 选择"插入"选项卡,"插图"功能组,"形状&quo ...

  7. Mysql高性能优化

    一.背景 最近公司项目添加新功能,上线后发现有些功能的列表查询时间很久.原因是新功能用到旧功能的接口,而这些旧接口的 SQL 查询语句关联5,6张表且编写不够规范,导致 MySQL 在执行 SQL 语 ...

  8. Kubernetes API作为权威接口,Kubernetes将成为软件的通用控制平面

    1创新之处在于API这是有关 Kubernetes的两部分系列中的第一篇.第一部分是一个答案:影响Kubernetes设计的关键思想是什么?Kubernetes会将它与其他平台区分开来吗?第二部分是关 ...

  9. Vulnhub系列:Tomato(文件包含getshell)

    这个靶机挺有意思,它是通过文件包含漏洞进行的getshell,主要姿势是将含有一句话木马的内容记录到ssh的登录日志中,然后利用文件包含漏洞进行包含,从而拿到shell 0x01 靶机信息 靶机:To ...

  10. 纯手画WinForm的Alert提示弹出框

    纯手画WinForm的Alert弹框 一.窗体设置 设置以下属性: 属性名 属性值 说明 AutoScaleMode None 确定屏幕分辨率或字体更改时窗体如何缩放 BackColor 103, 1 ...