【转】Python中自定义可迭代对象
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 函数有以下作用。
- 检查对象是否实现了
__iter__方法, 如果实现了就调用它, 获取一个迭代器。 - 如果没有实现
__iter__方法, 但是实现了__getitem__方法,Python 会创建一个迭代器, 尝试按顺序(从索引 0 开始) 获取元素。 - 如果尝试失败, Python 抛出 TypeError 异常, 通常会提示“C object is not iterable”(C 对象不可迭代) , 其中 C 是目标对象所属的类。
任何 Python 序列都可迭代的原因是, 它们都实现了__getitem__函数。 其实, 标准的序列都实现了__iter__函数, 因此你也应该这么做。
总结
- 因此我们在自定义可迭代对象需要实现
__iter__函数 - 严格来讲,我们还需要实现
__getitem__函数,这个函数的主要作用是当前对象可通过下标取值
另外,如果有一个未知的对象,我们怎么判断该对象是否可迭代呢,两种方式:
iter(x)
这是最准确的判断方式,传入要判断的对象,只要对象实现了__getitem__ 、 __iter__中的其中一个,该对象都是可迭代的,否则抛出TypeError: 'C' object is not iterable 异常;这儿有个区别,如果仅仅实现了 getitem ,调用 iter(x) 返回的是迭代器对象,如果实现的是 iter ,那么调用 iter(x) 返回的是生成器对象;isinstance(x, abc.Iterable)
该方式会自动忽略 getitem 函数,仅当对象实现了 iter 函数才返回 True,其他一律返回 False
原文链接:https://www.jianshu.com/p/048d40d86759
【转】Python中自定义可迭代对象的更多相关文章
- Python中的可迭代对象
Python中的可迭代对象有:列表.元组.字典.字符串:常结合for循环使用: 判断一个对象是不是可迭代对象: from collections import Iterable isinstanc ...
- Python中的可迭代对象与迭代器对象
刚刚学习Python,对“可迭代对象”和"迭代器对象"的个人理解,不知道对不对. 1.几个概念 (1)迭代工具:包括for循环.列表解析.in成员关系测试.....等等在内的,用于 ...
- Python中的可迭代对象/迭代器/For循环工作机制/生成器
本文分成6个部分: 1.iterable iterator区别 2.iterable的工作机制 3.iterator的工作机制 4.for循环的工作机制 5.generator的原理 6.总结 1.i ...
- Python中的可迭代对象,迭代器与生成器
先来看一张概览图,关于容器(container).可迭代对象(Iterable).迭代器(iterator).生成器(generator). 一.容器(container) 容器就是一个用来存储多个元 ...
- Python迭代器,可迭代对象,生成器
迭代器 迭代器(iterator)有时又称游标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如链表或阵列)上遍访的界面,设计人员无需关心容器物件的内存分配的实现细节. ...
- Python Cookbook(第3版)中文版:15.20 处理C语言中的可迭代对象
15.20 处理C语言中的可迭代对象¶ 问题¶ 你想写C扩展代码处理来自任何可迭代对象如列表.元组.文件或生成器中的元素. 解决方案¶ 下面是一个C扩展函数例子,演示了怎样处理可迭代对象中的元素: s ...
- 【Python】【容器 | 迭代对象 | 迭代器 | 生成器 | 生成器表达式 | 协程 | 期物 | 任务】
Python 的 asyncio 类似于 C++ 的 Boost.Asio. 所谓「异步 IO」,就是你发起一个 IO 操作,却不用等它结束,你可以继续做其他事情,当它结束时,你会得到通知. Asyn ...
- Python:容器、迭代对象、迭代器、生成器及yield关键字
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...
- python中的一切皆对象
python中一切皆对象是这个语言灵活的根本.函数和类也是对象,属于python的一等公民.包括代码包和模块也都是对象.python的面向对象更加彻底. 可以赋值给一个变量可以添加到集合对象中可以作为 ...
随机推荐
- 高效位运算 __builtin_系列函数
•int __builtin_ffs (unsigned int x) 返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4. •int __builtin_clz ...
- HTML网页设计基础笔记 • 【第8章 页面布局与规划】
全部章节 >>>> 本章目录 8.1 表格布局 8.1.1 表格布局 8.2 流式布局 8.2.1 瀑布流布局 8.2.2 masonry 实现瀑布流布局 8.3 div ...
- MySQL数据操作与查询笔记 • 【第3章 DDL 和 DML】
全部章节 >>>> 本章目录 3.1 使用 DDL 定义数据库表结构 3.1.1 SQL 简介 3.1.2 维护数据库和创建数据表 3.2 使用 DDL 维护数据库表结构 ...
- SpringBoot中JPA使用动态SQL查询
https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...
- SpringCloud创建项目父工程
1.说明 本文详解介绍Spring Cloud项目的父工程创建, 由于Spring Cloud项目下有很多模块组件, 需要先创建一个大的父工程项目, 然后在下面创建各个子工程模块. 2.创建父工程 这 ...
- C#自定义转换(implicit 或 explicit)
C#的类型转换分为显式转换和隐式转换,显式转换需要自己声明转换类型,而隐式转换由编译器自动完成,无需我们声明,如: //long需要显式转换成int long l = 1L; int i = (int ...
- Kubernetes 中的 Pod 安全策略
来源:伪架构师作者:崔秀龙很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:•SecurityContext 是 Pod 中的一个字 ...
- leetcode 347. 前 K 个高频元素
问题描述 给定一个非空的整数数组,返回其中出现频率前 k 高的元素. 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums ...
- Java类与对象的创建
以类的方式组织代码,以对象的方式组织(封装)数据 组织代码(类) public class Demo04 { String name;//默认值null int age;//默认值0 public v ...
- 【VictoriaMetrics】vm-select源码阅读
调用层次表格 源文件 行号 函数 说明 app/vmselect/main.go 63 main 入口 92行调用 requestHandler app/vmselect/main.go 132 -r ...