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. jboss CVE-2015-7501 反序列化漏洞复现

    JBOSS反序列化漏洞 环境: vulfocus jboss CVE-2015-7501 云服务器 kali攻击机 基本原理:JBoss在/invoker/JMXInvokerServlet请求中读取 ...

  2. Bom 基本使用以及定时器 倒计时案例

    BOM 是浏览器对象模型 它提供了独立内容而与浏览器窗口进行交互的对象,其核心对象是window 窗口加载事件 注意:window.onload 就可以吧JS代码写在页面元素的上方,因为onload是 ...

  3. CF149D游戏

    题目描述 Petya遇到了一个关于括号序列的问题: 给定一个字符串S,它代表着正确的括号序列,即("(")与 (")")是匹配的.例如:"(())() ...

  4. Java安全之Spring内存马

    Java安全之Spring内存马 基础知识 Bean bean 是 Spring 框架的一个核心概念,它是构成应用程序的主干,并且是由 Spring IoC 容器负责实例化.配置.组装和管理的对象. ...

  5. vue3+vant h5: Rem 移动端布局适配之postcss-pxtorem和lib-flexible

    如果不引入插件的话:ui稿的px转化成rem需自己计算 根据设计稿我们需要自己计算元素的rem(假如我们将html根元素font-size设置为41.4px): 那么1rem=41.4px; ui稿上 ...

  6. 论文解读二代GCN《Convolutional Neural Networks on Graphs with Fast Localized Spectral Filtering》

    Paper Information Title:Convolutional Neural Networks on Graphs with Fast Localized Spectral Filteri ...

  7. 【reverse】逆向4 初识堆栈

    [reverse]逆向4 初识堆栈 1.问题引入 假设我们需要一块内存,有如下的要求 主要用于临时存储一些数据(如果数据很少可以放入寄存器中) 能够记录存了多少数据 能够非常快速的找到某个数据 2.模 ...

  8. gin中的文件上传

    1. 单文件上传 package main import ( "fmt" "github.com/gin-gonic/gin" "log" ...

  9. JavaWeb后端工程师技能图

  10. MySQL存储引擎(最全面的概括)

    目录 一:MySQL存储引擎 1.什么是存储引擎? 2.查看存储引擎信息 二:MySQL支持的存储引擎 1.存储引擎 三:innoDB存储引擎 1.特性 2.存储结构 3.优缺点.适用场景 四:MyI ...