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. Swoole 中使用 Atomic 实现进程间无锁计数器

    使用示例: $atomic = new Swoole\Atomic(); $serv = new Swoole\Server('127.0.0.1', '9501'); $serv->set([ ...

  2. RazorEngine.NetCore 相见恨晚,它让我彻底放弃了T4模板

    在dbfrist 时代,用T4模板生成代码,貌似还没有感觉到别扭.但是到了codefrist 后,我想要实体生成生成备注,我就得想方设法的去把备注弄到数据库,然后 还要处理模型中类型像枚举这种属性,渐 ...

  3. MongoDB_文档存储结构(三)

    MongoDB 文档数据库的存储结构分为四个层次,从大到小依次是:数据库(database).集合(collection).文档(document).键值对. 图 1 描述了 MongoDB 与 My ...

  4. 异常 finally

    经典面试题:  程序执行结果是100: (一):final和finally和finalize的区别

  5. LCT小记

    不用说了,直接上怎么 die( 千万不要和 Treap 一样写左旋 zig 和右旋 zag,莫名死亡.Splay 只支持一个 rotate 上旋一个节点即可. splay() 之前记得弄一个栈存储 u ...

  6. 【Java】GUI实现贪吃蛇

    [Java]GUI实现贪吃蛇 前言 我们在做这个小游戏之前,得确保自己的AWT和Swing有一定的基础,并且会写一些简单的逻辑操作.这些都会在后面写的时候体现出来. 狂神老师从这里开始讲贪吃蛇的 我们 ...

  7. VictoriaMerics学习笔记(1):翻译官方广告

    先看看VictoriaMetrics官网网站上是如何作(tree)宣(new)传(bee)的: 官方广告 0.(监控领域)最快解决方案 为高性能而设计 便于安装 支持单机和群集版本 1.更高效的存储空 ...

  8. prometheus+exporter小测试:

    1.golang中使用expoter import ( "github.com/prometheus/client_golang/prometheus/promhttp" ) fu ...

  9. go面试题-基础类

    go基础类 1. go优势 * 天生支持并发,性能高 * 单一的标准代码格式,比其它语言更具可读性 * 自动垃圾收集比java和python更有效,因为它与程序同时执行 go数据类型 int stri ...

  10. 集合框架-工具类-JDK5.0特性-静态导入

    1 package cn.itcast.p4.news.demo; 2 3 import java.util.ArrayList; 4 //import java.util.Collections; ...