Python迭代器的实现原理
作者:??编程学习网???? 发布时间:2022-12-13 09:26:22
标签:Python,迭代器,原理
前言:
在Python里面,只要类型对象实现了__iter__,那么它的实例对象就被称为可迭代对象(Iterable),比如字符串、元组、列表、字典、集合等等。而整数、浮点数,由于其类型对象没有实现__iter__,所以它们不是可迭代对象。
from typing import Iterable
print(
isinstance("", Iterable),
isinstance((), Iterable),
isinstance([], Iterable),
isinstance({}, Iterable),
isinstance(set(), Iterable),
) # True True True True True
print(
isinstance(0, Iterable),
isinstance(0.0, Iterable),
) # False False
可迭代对象的一大特点就是它可以使用for循环进行遍历,但是能被for循环遍历的则不一定是可迭代对象。
我们举个栗子:
class A:
def __getitem__(self, item):
return f"参数item: {item}"
a = A()
#内部定义了 __getitem__
#首先可以让实例对象像字典一样访问属性
print(a["name"]) # 参数item: name
print(a["satori"]) # 参数item: satori
# 此外还可以像可迭代对象一样被for循环
# 循环的时候会自动给item传值,0 1 2 3...
# 如果内部出现了StopIteration,循环结束
# 否则会一直循环下去。这里我们手动break
for idx, val in enumerate(a):
print(val)
if idx == 5:
break
"""
参数item: 0
参数item: 1
参数item: 2
参数item: 3
参数item: 4
参数item: 5
"""
所以实现了__getitem__的类的实例,也是可以被for循环的,但它并不是可迭代对象。
from typing import Iterable
print(isinstance(a, Iterable)) # False
打印的结果是 False。
总之判断一个对象是否是可迭代对象,就看它的类型对象有没有实现__iter__。可迭代对象我们知道了,那什么是迭代器呢?很简单,调用可迭代对象的__iter__方法,得到的就是迭代器。
迭代器的创建
不同类型的对象,都有自己的迭代器,举个栗子:
lst = [1, 2, 3]
#底层调用的其实是list.__iter__(lst)
#或者说PyList_Type.tp_iter(lst)
it = lst.__iter__()
print(it) # <list_iterator object at 0x000001DC6E898640>
print(
str.__iter__("")
) # <str_iterator object at 0x000001DC911B8070>
print(
tuple.__iter__(())
) # <tuple_iterator object at 0x000001DC911B8070>
迭代器也是可迭代对象,只不过迭代器内部的__iter__返回的还是它本身。当然啦,在创建迭代器的时候,我们更常用内置函数iter。
lst = [1, 2, 3]
# 等价于 type(lst).__iter__(lst)
it = iter(lst)
但是iter函数还有一个鲜为人知的用法,我们来看一下:
val = 0
def foo():
global val
val += 1
return val
# iter可以接收一个参数: iter(可迭代对象)
# iter也可以接收两个参数: iter(可调用对象, value)
for i in iter(foo, 5):
print(i)
"""
1
2
3
4
"""
进行迭代的时候,会不停地调用接收的可调用对象,直到返回值等于传递第二个参数value,在底层被称为哨兵,然后终止迭代。
我们看一下iter函数的底层实现:
static PyObject *
builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *v;
// iter函数要么接收一个参数, 要么接收两个参数
if (!_PyArg_CheckPositional("iter", nargs, 1, 2))
return NULL;
v = args[0];
//如果接收一个参数
//那么直接使用 PyObject_GetIter 获取对应的迭代器即可
//可迭代对象的类型不同,那么得到的迭代器也不同
if (nargs == 1)
return PyObject_GetIter(v);
// 如果接收的不是一个参数, 那么一定是两个参数
// 如果是两个参数, 那么第一个参数一定是可调用对象
if (!PyCallable_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"iter(v, w): v must be callable");
return NULL;
}
// 获取value(哨兵)
PyObject *sentinel = args[1];
//调用PyCallIter_New
//得到一个可调用的迭代器, calliterobject 对象
/*
位于 Objects/iterobject.c 中
typedef struct {
PyObject_HEAD
PyObject *it_callable;
PyObject *it_sentinel;
} calliterobject;
*/
return PyCallIter_New(v, sentinel);
}
来源:https://juejin.cn/post/7091845218299248647
0
投稿
猜你喜欢
- 如下所示:# x = ['c b a',"e d f"]# y = []# for i in x:# f
- 1.Python 程序from flask import Flaskapp = Flask(__name__)@app.route('
- 我的坐标是深圳,2022年以来,大部分时候要求24小时,少部分时候要求48小时,更少的时候要求72小时,没有更长的情况。本文根据我的核酸检测
- 如下所示:def save(data, path): f = xlwt.Workbook() # 创建工作簿 she
- select语句中只能使用sql函数对字段进行操作(链接sql server),select 字段1 from 表1 where 字段1.I
- HTTP协议简介超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒
- 前言最近在网上搜了许多关于pandas.DataFrame的操作说明,都是一些基础的操作,但是这些操作组合起来还是比较费时间去正确操作Dat
- Python常见的异常提示及含义对照表如下:异常名称描述BaseException所有异常的基类SystemExit解释器请求退出Keybo
- 一、前情提要最近在写一个项目,需要用到子线程,但是我们小学二年级就学过操作系统, 线程的执行是由系统的CPU调度算法所决定的,调度算法按照一
- 假设前提:每天晚上10点到早上5点,每10分钟定时执行存储过程。实现方式:第一种是利用Mysql本身实现,制定event定时任务,可以借助N
- Django带来了一个高级的聚合生成框架,它使得创建RSS和Atom feeds变得非常容易。什么是RSS? 什么是Atom?RSS和Ato
- 使用 Rxjs,对于初学者来说,当我们处理 observables 错误的时候容易疑惑,因为我们会考虑使用 try-catch 方式捕获。但
- 本文实例讲述了Go语言基础知识。分享给大家供大家参考,具体如下:GO文件目录结构该图是go-windows的目录结构如图,go的程序应该是在
- 前言:python由于GIL(全局锁)的存在,不能发挥多核的优势,其性能一直饱受诟病。然而在IO密集型的网络编程里,异步处理比同步处理能提升
- 虽然说IE6除了部分要求苛刻的需求以外已经被可以不考虑了,但是WIN7自带的浏览器IE8还是需要支持的。本文这个方法主要的优点,个人觉得就是
- 相信做过自动化运维的同学都用过REST API接口来完成某些动作。API是一套成熟系统所必需的接口,可以被其他系统或脚本来调用,这也是自动化
- 你一定听说过这句著名的数据科学名言:在数据科学项目中, 80% 的时间是在做数据处理。如果你没有听过,那么请记住:数据清洗是数据科学工作流程
- Oracle物理结构故障是指构成数据库的各个物理文件损坏而导致的各种数据库故障。这些故障可能是由于硬件故障造成的,也可能是人为误操作而引起。
- 了解如何在sublime编辑器中安装python软件包,以实现自动完成等功能,并在sublime编辑器本身中运行build。安装Sublim
- 介绍在本文中,我们将使用 OpenCV 库来开发 Python 文档扫描器。OpenCV 的简要概述: OpenCV 是一个开源库,用于各种