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. 高效位运算 __builtin_系列函数

    •int __builtin_ffs (unsigned int x) 返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4. •int __builtin_clz ...

  2. HTML网页设计基础笔记 • 【第8章 页面布局与规划】

    全部章节   >>>> 本章目录 8.1 表格布局 8.1.1 表格布局 8.2 流式布局 8.2.1 瀑布流布局 8.2.2 masonry 实现瀑布流布局 8.3 div ...

  3. MySQL数据操作与查询笔记 • 【第3章 DDL 和 DML】

    全部章节   >>>> 本章目录 3.1 使用 DDL 定义数据库表结构 3.1.1 SQL 简介 3.1.2 维护数据库和创建数据表 3.2 使用 DDL 维护数据库表结构 ...

  4. SpringBoot中JPA使用动态SQL查询

    https://www.jianshu.com/p/f72d82e90948 可以重点关注方法二,把原生sql传入数据库去查询 好处是:更加灵活坏处是:拼接sql比较痛苦,也容易出问题,比如拼接的sq ...

  5. SpringCloud创建项目父工程

    1.说明 本文详解介绍Spring Cloud项目的父工程创建, 由于Spring Cloud项目下有很多模块组件, 需要先创建一个大的父工程项目, 然后在下面创建各个子工程模块. 2.创建父工程 这 ...

  6. C#自定义转换(implicit 或 explicit)

    C#的类型转换分为显式转换和隐式转换,显式转换需要自己声明转换类型,而隐式转换由编译器自动完成,无需我们声明,如: //long需要显式转换成int long l = 1L; int i = (int ...

  7. Kubernetes 中的 Pod 安全策略

    来源:伪架构师作者:崔秀龙很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:•SecurityContext 是 Pod 中的一个字 ...

  8. leetcode 347. 前 K 个高频元素

    问题描述 给定一个非空的整数数组,返回其中出现频率前 k 高的元素.   示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums ...

  9. Java类与对象的创建

    以类的方式组织代码,以对象的方式组织(封装)数据 组织代码(类) public class Demo04 { String name;//默认值null int age;//默认值0 public v ...

  10. 【VictoriaMetrics】vm-select源码阅读

    调用层次表格 源文件 行号 函数 说明 app/vmselect/main.go 63 main 入口 92行调用 requestHandler app/vmselect/main.go 132 -r ...