[转载] 【python魔术方法】迭代器(__iter__和__next__)

参考链接: Python __iter __()和__next __()| 将对象转换为迭代器

文章目录

 `__iter__` 和 `__next__`真正的迭代器总结

 

 

 

python里面有很多的以__开始和结尾的函数,利用它们可以完成很多复杂的逻辑代码,而且提高了代码的简洁性,本文主要总结了迭代器用到的魔术方法,并且主要以代码例子进行解释。 

__iter__ 和 __next__ 

其实这里需要引入一个概念,叫迭代器,常见的就是我们在使用for语句的时候,python内部其实是把for后面的对象上使用了内建函数iter,比如: 

a = [1, 2, 3]

for i in a:

    do_something()

 

其实在python内部进行了类似如下的转换: 

a = [1, 2, 3]

for i in iter(a):

    do_something()

 

那么iter返回的是什么呢,就是一个迭代对象,它主要映射到了类里面的__iter__函数,此函数返回的是一个实现了__next__的对象。注意理解这句话,比如: 

class B(object):

    def __next__(self):

        raise StopIteration

 

class A(object):

    def __iter__(self):

        return B()

 

我们可以看见,A这个类实现了一个__iter__函数,返回的是B()的实例对象,其中B里面实现了__next__这个函数。 

下面引入几个概念: Iterable: 有迭代能力的对象,一个类,实现了__iter__,那么就认为它有迭代能力,通常此函数必须返回一个实现了__next__的对象,如果自己实现了,你可以返回self,当然这个返回值不是必须的; Iterator: 迭代器(当然也是Iterable),同时实现了__iter__和__next__的对象,缺少任何一个都不算是Iterator,比如上面例子中,A()可以是一个Iterable,但是A()和B()都不能算是和Iterator,因为A只实现了__iter__,而B只实现了__next__()。 

我们可以使用collections里面的类型来进行验证: 

class B(object):

    def __next__(self):

        raise StopIteration

 

class A(object):

    def __iter__(self):

        return B()

 

 

from collections.abc import *

 

a = A()

b = B()

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

 

print(isinstance(b, Iterable))

print(isinstance(b, Iterator))

 

结果是: 

True

False

False

False

 

让我们稍微对B这个类做一点修改: 

class B(object):

    def __next__(self):

        raise StopIteration

 

    def __iter__(self):

        return None

 

class A(object):

    def __iter__(self):

        return B()

 

 

from collections.abc import *

 

a = A()

b = B()

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

 

print(isinstance(b, Iterable))

print(isinstance(b, Iterator))

 

结果是: 

True

False

True

True

 

真正的迭代器 

上面只是做了几个演示,这里具体说明一下: 当调用iter函数的时候,生成了一个迭代对象,要求__iter__必须返回一个实现了__next__的对象,我们就可以通过next函数访问这个对象的下一个元素了,并且在你不想继续有迭代的情况下抛出一个StopIteration的异常(for语句会捕获这个异常,并且自动结束for),下面实现了一个自己的类似range函数的功能。 

class MyRange(object):

    def __init__(self, end):

        self.start = 0

        self.end = end

 

    def __iter__(self):

        return self

 

    def __next__(self):

        if self.start < self.end:

            ret = self.start

            self.start += 1

            return ret

        else:

            raise StopIteration

 

from collections.abc import *

 

a = MyRange(5)

print(isinstance(a, Iterable))

print(isinstance(a, Iterator))

 

for i in a:

    print(i)

 

结果是: 

True

True

0

1

2

3

4

 

接下来我们使用next函数模拟一次: 

class MyRange(object):

    def __init__(self, end):

        self.start = 0

        self.end = end

 

    def __iter__(self):

        return self

 

    def __next__(self):

        if self.start < self.end:

            ret = self.start

            self.start += 1

            return ret

        else:

            raise StopIteration

 

a = MyRange(5)

print(next(a))

print(next(a))

print(next(a))

print(next(a))

print(next(a))

print(next(a)) # 其实到这里已经完成了,我们在运行一次查看异常

 

可以看见一个很明显的好处是,每次产生的数据,是产生一个用一个,什么意思呢,比如我要遍历[0, 1, 2, 3.....]一直到10亿,如果使用列表的方式,那么是会全部载入内存的,但是如果使用迭代器,可以看见,当用到了(也就是在调用了next)才会产生对应的数字,这样就可以节约内存了,这是一种懒惰的加载方式。 

总结 

可以使用collection.abs里面的Iterator和Iterable配合isinstance函数来判断一个对象是否是可迭代的,是否是迭代器对象iter实际是映射到了__iter__函数只要实现了__iter__的对象就是可迭代对象(Iterable),正常情况下,应该返回一个实现了__next__的对象(虽然这个要求不强制),如果自己实现了__next__,当然也可以返回自己同时实现了__iter__和__next__的是迭代器(Iterator),当然也是一个可迭代对象了,其中__next__应该在迭代完成后,抛出一个StopIteration异常for语句会自动处理这个StopIteration异常以便结束for循环 

生成器相关的文档已经在这里。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540465.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Silverlight 异步单元测试

Silverlight 中的很多操作都是异步的&#xff0c;很多情况下要求单元测试也是异步的&#xff0c;但是介绍异步单元测试的文档很少。通过对 Silverlight Toolkit 中的 Microsoft.Silverlight.Testing 和 Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight 这两个文件…

网络拓扑 令牌环网 以太网_以太网连接中网络拓扑的类型及其框架 以太网技术...

网络拓扑 令牌环网 以太网A topology explains how physically the network is designed or what is the structure of the network. These designs are both physical and logical. There are many network topologies 4 like Bus, Star, Ring, and Mesh. But only two types …

Wafer晶圆封装工艺介绍

芯片封装的目的&#xff08;The purpose of chip packaging&#xff09;: 芯片上的IC管芯被切割以进行管芯间连接&#xff0c;通过引线键合连接外部引脚&#xff0c;然后进行成型&#xff0c;以保护电子封装器件免受环境污染&#xff08;水分、温度、污染物等&#xff09;&…

[转载] Python中的解析式和生成器表达式

参考链接&#xff1a; Python | 生成器表达式 解析式和生成器表达式 列表解析List Comprehension 语法 [返回值 for 元素 in 可迭代对象 if 条件]使用中括号[],内部是for循环&#xff0c;if条件语句可选&#xff0c;会返回一个新的列表 列表解析试优点 编译器会优化&…

java 数字字母进位_使用带有进位的8085微处理器将两个8位数字相乘

java 数字字母进位Problem statement: 问题陈述&#xff1a; Multiplication of two 8 bits numbers using 8085 microprocessor with carry. 使用带有进位的8085微处理器将两个8位数字相乘。 Algorithm: 算法&#xff1a; Load HL pair with initial data using LHLD comma…

[转载] Python3.0中普通方法、类方法和静态方法的比较

参考链接&#xff1a; Python中的类方法与静态方法 一、语法区别 刚接触Python中的面向对象&#xff0c;对于类方法和静态方法难以区分&#xff0c;通过查找知乎、CSDN论坛&#xff0c;废了好大的劲思路才逐渐明朗&#xff0c;所以就总结顺便分享一下。 首先开始编辑代码 # 普…

iOS:个人浅谈工厂模式

一、什么是工厂方法&#xff1f; 正式的解释是&#xff1a;在基类中定义创建对象的一个接口&#xff0c;让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。工厂方法要解决的问题是对象的创建时机&#xff0c;它提供了一种扩展的策略&#xff0c;很好地符合了…

scanf 输入十六进制_使用C语言中的scanf()在字符变量中输入十进制,八进制和十六进制值...

scanf 输入十六进制Here, we will declare an unsigned char variable and input different formats value like decimal format, octal format and hexadecimal format. 在这里&#xff0c;我们将声明一个无符号的char变量&#xff0c;并输入不同格式的值&#xff0c;例如十进…

[转载] Python中pass的作用

参考链接&#xff1a; 如何在Python中编写空函数&#xff1f;请使用 pass语句 空语句 do nothing保证格式完整保证语义完整 以if语句为例&#xff0c;在c或c/java中&#xff1a; if(true) ; //do nothing else { //do something } 对应于python就要这样写&#xff…

wrf 嵌套网格作用_在网格系统中使用响应列,嵌套列和偏移列 引导程序

wrf 嵌套网格作用介绍 (Introduction) In the previous article, we have learnt what is grid and grid system and how it works? Now, we will learn about how Responsive column, Nesting Columns and Offset Columns works and how to use them? If you have any doubt…

[看书笔记]《深入java虚拟机》——java体系结构(二)

java虚拟机的三种含义&#xff1a; - 抽象的规范 - 一个具体的实现 - 一个运行中的虚拟机实例 ---------------------java虚拟机的生命周期&#xff1a; java虚拟机实例的天职就是负责运行一个java程序。 启动一个java程序&#xff0c;一个虚拟机实例诞生了&#xff1b;程序关闭…

[转载] 【零基础学爬虫】python中的yield详解

参考链接&#xff1a; 什么时候在Python中使用yield而不是return python中的yield功能比较强大&#xff0c;什么意思呢&#xff1f;如果一个函数f内使用了yield关键词&#xff0c;那么该函数就可以这样使用&#xff1a; for item in f(***): **** 也就是包含yield关键词的函…

全新的membership框架Asp.net Identity(1)——.Net membership的历史

在Asp.net上&#xff0c;微软的membershop框架经历了Asp.net membership到Asp.net simple membership&#xff0c;再到现在的Asp.net Identity. 每一次改变&#xff0c;都使得验证框架更加的适应变化和可定制。这篇文章是Asp.net Identity系列的开篇&#xff0c;主要就membersh…

c语言100位整数变量声明_C ++程序动态声明一个整数变量并打印其内存地址

c语言100位整数变量声明Here, we will learn how we can declare an integer variable dynamically and how to print address of declared memory block? 在这里&#xff0c;我们将学习如何动态声明整数变量&#xff0c;以及如何打印声明的内存块的地址&#xff1f; In C pr…

[转载] python 函数返回多个值

参考链接&#xff1a; 在Python中返回多个值 &#xff08;廖雪峰Python教程学习笔记&#xff09; 函数体内部的语句在执行时&#xff0c;一旦执行到return&#xff0c;函数就执行完毕&#xff0c;并将结果返回。 如果没有return语句&#xff0c;函数执行完毕后也会返回结果…

二.编写第一个c#程序(注释,命名空间,类,Main方法,标识符,关键字,输入,输出语句,)...

复习编写一个控制台应用程序&#xff0c;目标是在控制台输出“Hello World” 1.第一步&#xff0c;打开Visual Studio 2012以上版本(我用的是VS 2015)&#xff0c;打开完成后出现以下界面 2.第二步&#xff0c;这时候就要新建一个解决方案了&#xff0c;创建解决方案可以直接点…

[转载] Python中定义函数,循环语句,条件语句

参考链接&#xff1a; Python中的局部函数 由于日常程序流中主要是三种结构&#xff1a;顺序&#xff0c;循环&#xff0c;条件&#xff0c;且往往需要自定义函数再调用&#xff0c; 因此今天想学习一下Python中关于定义函数、循环语句和条件语句的写法。 1.定义函数 区…

node oauth2验证_如何设置和使用护照OAuth Facebook身份验证(第1部分)| Node.js

node oauth2验证In my last articles, we looked at the implementation of the passport-local authentication strategy. We also looked at the various requirements to get started with the login form. 在上一篇文章中&#xff0c;我们介绍了护照本地身份验证策略的实现…

vue2.0 引用qrcode.js实现获取改变二维码的样式

vue代码 <template><div class"qart"><div id"qrcode" ref"qrcode"></div><input type"text" id"getval" value"" placeholder"修改这个值改变二维码"></div> <…

[转载] Python列表排序 list.sort方法和内置函数sorted

参考链接&#xff1a; Python中的函数 Python列表排序 list.sort方法和内置函数sorted 很多时候我们获取到一个列表后,这个列表并不满足我们的需求,我们需要的是一个有特殊顺序的列表. 这时候就可以使用list.sort方法和内置函数sorted,本文就是介绍list.sort方法和sorted内…