python迭代器详解

不懂的问题:什么是协变、逆变?渐进式?

_T_co = TypeVar("_T_co", covariant=True)  # Any type covariant containers.
  • 作者:20岁爱吃必胜客(坤制作人),近十年开发经验, 跨域学习者,目前于海外某世界知名高校就读计算机相关专业。
  • 荣誉:阿里云博客专家认证、腾讯开发者社区优质创作者,在CTF省赛校赛多次取得好成绩。
  • 跨领域学习,喜欢摄影、弹吉他、咏春拳。文章深入浅出、语言风趣;爱吃必胜客社区创立者,旨在“发现美 欣赏美

  • 🏆 学习系列专栏
    。🏅 Python学习宝库
    。🏅 网络安全学习宝库

在这里插入图片描述

在这里插入图片描述

文章目录

  • ⭐️迭代器详解
    • 🌟迭代器示例
    • 🌟__iter__()与__next__()方法解释
    • 🌟常用迭代器zip和enumerate
    • 🌟itertools模块提供的各种迭代器类型
    • 🌟 源码
    • 🌟Python迭代器常见的用法
  • ⭐️迭代器与生成器的区别
    • 🌟生成器的例子
  • ⭐️迭代器的内部实现
  • ⭐️总结
    • 🌟__next__(),__iter__()详细解释
    • 🌟 魔法函数实现原理
    • 🌟 我的故事

⭐️迭代器详解

在这里插入图片描述
Python迭代器是Python编程语言中非常常用的一种工具。它是访问容器(例如列表、元组等)中的元素的一种方式,可以逐个访问容器中的元素,而不必整个容器存储在内存中。

Python迭代器可以被定义为:

  1. 一个实现了__iter__()方法的对象;
  2. 通过调用__next__()方法来逐个访问容器中的元素。

🌟迭代器示例

下面是一个简单的Python迭代器示例:

class MyIterator:
  def __init__(self, lst):
    self.lst = lst# 列表
    self.index = 0# 索引

  def __iter__(self):
    return self

  def __next__(self):
    if self.index < len(self.lst):
      value = self.lst[self.index]
      self.index += 1
      return value
    else:
      raise StopIteration

在这个示例中,我们创建了一个称为"MyIterator"的类,它包含了一个列表和一个索引值。该类还实现了__iter__()__next__()方法。

🌟__iter__()与__next__()方法解释

__iter__()方法返回该对象本身,因此可以直接对该对象使用for...in...语句进行迭代。__next__()方法则根据当前索引值来获取列表中的下一个元素,如果已经到达列表末尾,则抛出StopIteration异常。

以下是一个使用MyIterator迭代器的示例:

my_list = [1, 2, 3, 4, 5]
my_iter = MyIterator(my_list)
for item in my_iter:
  print(item)

执行结果为:

1
2
3
4
5

这是一个简单的例子,实际上Python迭代器可以应用于许多不同类型的容器,包括列表、元组、字典以及文件等

🌟常用迭代器zip和enumerate

在Python标准库中,还提供了一些常用的迭代器,例如enumerate()zip()

从更深层次上来讲,Python迭代器是支持惰性计算(lazy evaluation)的一种工具。惰性计算指的是在需要时才进行计算,而非提前将所有的计算都执行完毕。对于大型数据集合,惰性计算可以节省内存开销并提高程序性能。
Python迭代器的另一个特点是可逆性(reversibility),也就是说我们可以通过反向迭代器(reverse iterator)逆序访问容器中的元素。Python标准库中提供了reversed()函数用于创建反向迭代器。以下是一个简单示例:

my_list = [1, 2, 3, 4, 5]
for item in reversed(my_list):
  print(item)

执行结果为:

5
4
3
2
1

🌟itertools模块提供的各种迭代器类型

此外,Python迭代器还支持使用itertools模块提供的各种迭代器类型,例如cycle()count()groupby()等。

需要注意的是,Python 2.x版本中的迭代器实现与Python 3.x有所不同,因此在编写跨Python版本的代码时应当谨慎。

总的来说,Python迭代器是Python编程语言中非常强大和灵活的工具,可以应用于各种场景和数据类型,帮助我们更加高效地处理数据和任务。

🌟 源码

class Iterator(Iterable[_T_co], Protocol[_T_co]):
    @abstractmethod
    def __next__(self) -> _T_co: ...
    def __iter__(self) -> Iterator[_T_co]: ...
    
class Iterable(Protocol[_T_co]):
    @abstractmethod
    def __iter__(self) -> Iterator[_T_co]: ...

🌟Python迭代器常见的用法

  1. 计算斐波那契数列

斐波那契数列是指从0和1开始,后续的每一项都是前面两项的和。使用Python迭代器可以很方便地计算斐波那契数列

class Fib:
    def __init__(self, max):
        self.max = max

    def __iter__(self):
        self.a = 0
        self.b = 1
        return self

    def __next__(self):
        fib = self.a
        if fib > self.max:
            raise StopIteration
        self.a, self.b = self.b, self.a + self.b
        return fib

以上代码定义了一个Fib类,实现了__iter____next__两个方法,该类实现了一个迭代器,可以使用for-in语句遍历所有小于max的斐波那契数列元素。

  1. 读取大型文件数据

当我们需要处理大量数据时,将整个数据集加载到内存中可能会导致程序崩溃或效率低下。使用Python迭代器来处理大型文件数据非常理想,这种方式只在内存中维护当前处理的数据块,而不需要一次性读取整个文件。

with open('large_file.txt', 'r') as f:
    for line in f:
        process_line(line)

以上代码打开一个大型文件并使用for-in语句迭代遍历每一行数据,可以在不占用太多内存的情况下逐行处理文件。

  1. 实现生成器函数

除了使用类来定义迭代器,Python还支持使用生成器函数(generator function)来实现迭代器。生成器函数可以通过yield语句来产生值,当生成器被调用时,它将返回一个可迭代对象,使用for-in语句可以遍历这个可迭代对象。

def my_generator(max):
    for i in range(max):
        yield i

for item in my_generator(5):
    print(item)

以上代码定义了一个生成器函数my_generator,使用yield语句来产生0~max-1的数字。使用for-in语句可以遍历这个生成器函数产生的可迭代对象,输出结果为:

0
1
2
3
4

⭐️迭代器与生成器的区别

在Python中,除了迭代器外,还有一种非常常见的工具就是生成器(generator)。两者都可以用yield语句实现,但它们有一些区别。

  • 迭代器必须实现__iter____next__方法,而生成器只需要实现一个yield语句即可。
  • 生成器可以保存状态,每次调用yield语句时会自动保存当前的局部变量和执行位置,并在下一次调用时恢复执行状态,从而实现了迭代器的功能。
  • 生成器的主要作用是生成序列,而迭代器则可以用于各种数据结构的遍历,包括序列、映射、文件等。

🌟生成器的例子

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

以上代码定义了一个名为fibonacci的生成器,它可以按照斐波那契数列的规律不断生成新的数值。我们可以使用for-in语句来迭代这个生成器,也可以使用next函数单独获取它的下一个值:

f = fibonacci()
print(next(f))  # 输出 0
print(next(f))  # 输出 1
print(next(f))  # 输出 1
print(next(f))  # 输出 2

⭐️迭代器的内部实现

Python中的迭代器实际上是基于协议(protocol)实现的,它需要满足两个条件:

  • 实现__iter__方法并返回self
  • 实现__next__方法,并在每次调用时返回下一个值,如果没有下一个值则抛出StopIteration异常。

在Python中,任意对象只要满足以上两个条件就可以作为迭代器使用。以下是一个简单的自定义迭代器的例子:

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.data):
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

以上代码定义了一个名为MyIterator的迭代器类,它包含了一个列表作为数据源

⭐️总结

__iter__():迭代器,生成迭代对象时调用,返回值必须是对象自己,然后for可以循环调用next方法

__next__():每一次for循环都调用该方法(必须存在

🌟__next__(),iter()详细解释

在 Python 中,使用 __next__()__iter__() 方法可以创建一个迭代器对象。迭代器是一种特殊的对象,它允许我们逐个访问容器中的元素,而不必预先将整个容器加载到内存中。

下面是 __next__()__iter__() 的代码和讲解:

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        #@summary: 迭代器,生成迭代对象时调用,
        #返回值必须是对象自己,然后for可以循环调用next方法

        return self

    def __next__(self):
    #  @summary: 每一次for循环都调用该方法(必须存在)
        if self.index >= len(self.data):
            # 抛出 StopIteration 异常,表示迭代结束
            raise StopIteration
        value = self.data[self.index]
        self.index += 1
        return value

在上面的代码中,创建了一个名为 MyIterator 的迭代器类。该迭代器类包含以下两个方法:

  • __init__(self, data):构造函数,接受一个参数 data,即需要遍历的数据。
  • __iter__(self):实现可迭代协议返回当前对象的迭代器对象,即返回 self。
  • __next__(self):实现迭代器协议,返回容器中的下一个元素,如果没有更多元素,则抛出 StopIteration 异常。

现在,我们可以使用这个迭代器来遍历任何可迭代对象(如列表、元组、字典等)。下面是使用 MyIterator 迭代器来遍历一个列表的示例代码:

my_list = [1, 2, 3, 4, 5]
my_iterator = MyIterator(my_list)

for i in my_iterator:
    print(i)

在上面的代码中,我们首先创建了一个包含 5 个元素的列表 my_list。然后,我们创建了一个 MyIterator 对象 my_iterator,并将 my_list 作为参数传递给它。最后,我们使用 for 循环来遍历这个迭代器,从而遍历 my_list 中的所有元素。

通过上述示例代码可以看出,使用 __next__()__iter__() 方法可以创建一个自定义的迭代器对象,并用于遍历任何可迭代的对象

🌟 魔法函数实现原理

Python中的“魔法函数”是一种特殊的函数,其名称以双下划线“__”开头和结尾,例如“init”,“call”等,这些函数在Python的类定义中起到了特殊的作用。魔法函数的实现原理是利用了Python语言的一些特性,即“特殊方法解释器”(SPECIAL METHOD LOOKUP)。

特殊方法解释器的工作方式为:当对象接收到一个消息,但在该对象上没有对应的方法时,会自动查找并调用该对象所在类中的特殊方法,从而实现对该消息的处理。因此,魔法函数的作用就是为Python对象提供了默认的行为或操作,从而方便我们对对象进行操作或控制。

下面以一个简单的例子说明魔法函数的实现原理

class MyClass:
    def __init__(self, x):
        self.x = x

    def __str__(self):
        return "MyClass with x = {}".format(self.x)

# 创建一个MyClass对象
obj = MyClass(10)

# 调用__str__魔法函数
print(obj)

上述代码定义了一个名为MyClass的类,其中包含了__init__和__str__两个魔法函数。__init__用于初始化对象的属性,__str__用于返回对象的字符串表示形式。在创建MyClass对象并输出时,会自动调用__str__函数并返回对象的字符串表示形式。

这就是魔法函数的实现原理:当创建对象时,会自动调用__init__魔法函数进行初始化操作;当需要获取对象的字符串表示时,会自动调__str__函数。通过使用魔法函数,我们可以很方便地对Python对象进行操作和控制,从而提高程序的效率和可维护性。

除了__init__和__str__这两个常见的魔法函数外,Python语言内置了大量的其他魔法函数,例如:

  • call(self, *args, **kwargs): 使对象可以像函数一样被调用;
  • getitem(self, key): 实现对象的索引访问;
  • setitem(self, key, value): 实现对象的索引赋值;
  • len(self): 返回对象的长度;
  • add(self, other): 实现对象的加法运算;
  • eq(self, other): 判断两个对象是否相等;

通过定义这些内置的魔法函数,我们可以非常方便地实现自己的对象类型,支持各种操作和控制。例如,我们可以自定义一个矩阵类型,并实现其加法、乘法、转置等操作:

class Matrix:
    def __init__(self, data):
        self.data = data

    def __add__(self, other):
        result = []
        for i in range(len(self.data)):
            row = []
            for j in range(len(self.data[i])):
                row.append(self.data[i][j] + other.data[i][j])
            result.append(row)
        return Matrix(result)

    def __mul__(self, other):
        result = []
        for i in range(len(self.data)):
            row = []
            for j in range(len(other.data[0])):
                s = 0
                for k in range(len(self.data[i])):
                    s += self.data[i][k] * other.data[k][j]
                row.append(s)
            result.append(row)
        return Matrix(result)

    def transpose(self):
        result = []
        for i in range(len(self.data[0])):
            row = []
            for j in range(len(self.data)):
                row.append(self.data[j][i])
            result.append(row)
        return Matrix(result)

    def __str__(self):
        s = ""
        for i in range(len(self.data)):
            for j in range(len(self.data[i])):
                s += str(self.data[i][j]) + " "
            s += "\n"
        return s

# 创建两个矩阵
m1 = Matrix([[1, 2], [3, 4]])
m2 = Matrix([[5, 6], [7, 8]])

# 执行加法和乘法操作
print(m1 + 

🌟 我的故事

python学习之路任重而道远,要想学完说容易也容易,说难也难。 很多人说python最好学了,但扪心自问,你会用python做什么了?
刚开始在大学学习c语言,写一个飞行棋的小游戏,用dos界面来做,真是出力不讨好。 地图要自己一点一点画出来,就像这样:

================
|				|
|				|
|===============
从此讨厌编程,不想继续学下去。每次作业应付。
算法考试,数据结构考试随便背代码,只求通过。
最后呢?我学会变成了吗?只能对一些概念侃侃而谈,但真的会几行代码,能写出实用工具吗?
答案变得模糊。
所以我们要从现在开始,学好python,不要再糊弄下去!!!

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Docker】Network网络

文章目录网络情况查看宿主机网络情况 ifconfig查看docker网络模式命令 docker network ls常用基本命令查看网络 docker network ls查看网络源数据 docker network inspect XXX网络名字创建网络 docker network create test_network删除网络 docker network rm XXX网络名字netwo…

Kotlin~Adapter适配器模式

概念 Adapter&#xff08;Wrapper&#xff09; Pattern&#xff0c;连接两个不兼容的接口&#xff0c;让接口不兼容的对象能够相互合作。 适配器中的角色 请求者Client&#xff1a;调用者目标Target&#xff1a;定义了Client要使用的功能转化对象Adaptee&#xff1a; 需要适…

ROC-RK3588S-PC (Android 12) 看门狗的使用

&#x1f347; 博主主页&#xff1a; 【Systemcall小酒屋】&#x1f347; 博主追寻&#xff1a;热衷于用简单的案例讲述复杂的技术&#xff0c;“假传万卷书&#xff0c;真传一案例”&#xff0c;这是林群院士说过的一句话&#xff0c;另外“成就是最好的老师”&#xff0c;技术…

走进二叉树的世界 ———性质讲解

二叉树的性质和证明前言1.二叉树的概念和结构特殊的二叉树&#xff1a;二叉树的性质前言 本篇博客主要讲述的是有关二叉树的一些概念&#xff0c;性质以及部分性质的相关证明&#xff0c;如果大伙发现了啥错误&#xff0c;可以在评论区指出&#x1f618;&#x1f618; 1.二叉树…

Verilog之小规模经典电路设计

verilog语句执行顺序 每个语句块&#xff0c;是事件(event)触发执行的主要分为 连续赋值语句assign过程赋值语句always, initial(只执行一次) 连续和过程之间是并行执行的&#xff0c;只要满足出发条件即可assign是在后面的输入发生变化时进行执行always是在敏感列表发生变化时…

C语言数据结构初阶(8)----栈与队列OJ题

CSDN的uu们&#xff0c;大家好。这里是C语言数据结构的第八讲。 目标&#xff1a;前路坎坷&#xff0c;披荆斩棘&#xff0c;扶摇直上。 博客主页&#xff1a; 姬如祎 收录专栏&#xff1a;数据结构与算法栈与队列的知识点我➡➡队列相关点我➡➡栈相关2. 用栈实现队列原题链接…

C语言基础 — ( C语言的链表实例)

欢迎小伙伴的点评✨✨ 本篇章系列是对C语言的深度思考和总结、关于C语言内容会持续更新 文章目录前言一、什么是链表二、建立简单静态链表二、建立简单动态链表三、链表的增加、删除、更改、查询四、总结前言 本章会给大家带来基于C语言链表的实例。 一、什么是链表 链表是一…

Python解题 - CSDN周赛第40期

上期问哥没参加&#xff0c;但从赛后大家的反馈来看&#xff0c;又出现了数据上的bug&#xff0c;使用 python 的朋友会遇到第二个用例的柱子高度数组长度不够&#xff0c;200根柱子&#xff0c;只有179个数据&#xff0c;这让人怎么玩&#xff1f;但是用C的选手就没有这个问题…

面试官:vue2和vue3的区别有哪些

目录 多根节点&#xff0c;fragment&#xff08;碎片&#xff09; Composition API reactive 函数是用来创建响应式对象 Ref toRef toRefs 去除了管道 v-model的prop 和 event 默认名称会更改 vue2写法 Vue 3写法 vue3组件需要使用v-model时的写法 其他语法 1. 创…

提升网站性能:Nginx五种高效负载均衡策略

前言 本文收录于我是沐风晓月的csdn专栏《linux基本功-系统服务实战》&#xff0c; 关于nginx的系列后面会汇总起来&#xff0c;关注我&#xff0c;一起学习与成长。 本专栏写作的过程中&#xff0c;联合了csdn几位大佬&#xff0c;目前正在整理更新目录&#xff0c;力争让大…

多线程代码案例-阻塞队列

hi,大家好,今天为大家带来多线程案例--阻塞队列 这块知识点也很重要,要好好掌握呀~~~ &#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x1f338;&#x…

【蓝桥杯_练习】

蓝桥杯1.创建工程2.LED灯点亮led.c3.LCD液晶屏显示lcd.c4.定时器按键单机interrupt.hinterrupt.cman.c5.定时器&#xff08;长按键&#xff09;interrupt.hinterrupt.cmain.c6.PWMmain.c7.定时器-输入捕获&#xff08;频率&#xff0c;占空比测量&#xff09;interrupt.cmain.c…

中科亿海微FPGA应用(一、点灯)

1.软件&#xff1a; https://download.csdn.net/download/weixin_41784968/87564071 需要申请license才能使用&#xff1a;软件试用申请_软件试用申请_中科亿海微电子科技&#xff08;苏州&#xff09;有限公司 2.开发板&#xff1a; 芯片EQ6HL45&#xff0c;42.5k LUT。 3…

移植RK3568的串口

文章目录 前言一、代码位置二、硬件原理图三、修改设备树四、关闭串口调试功能总结前言 本文主要讲解如何移植RK3568的串口 提示:以下是本篇文章正文内容,下面案例可供参考 一、代码位置 drivers/tty/serial/8250/8250_core.c drivers/tty/serial/8250/8250_dma.c dma实现…

TCP协议详解

1.TCP的准备条件在古代的时候&#xff0c;古人们经常写书信进行交流&#xff0c;写书信的前提是你要知道这份信是要寄给谁在网络中&#xff0c;我们通过ip端口号找对目标对象&#xff0c;但是现在网站一般会对ip端口注册一个域名&#xff0c;所以我们一般就是对域名进行查找&am…

mysql的limit查询竟然有坑?

背景 最近项目联调的时候发现了分页查询的一个bug&#xff0c;分页查询总有数据查不出来或者重复查出。 数据库一共14条记录。 如果按照一页10条。那么第一页和第二页的查询SQL和和结果如下。 .png) 那么问题来了&#xff0c;查询第一页和第二页的时候都出现了11,12,13的记录…

又一款全新的基于 GPT4 的 Python 神器Cursor,关键还免费

chartgpt大火之后&#xff0c;随之而来的就是一大类衍生物了。 然后&#xff0c;今天要给大家介绍的是一款基于GPT4的新一代辅助编程神器——Cursor。 它最值得介绍的地方在于它免费&#xff0c;我们可以直接利用它来辅助我们编程&#xff0c;真正做到事半功倍。 注意&#…

大数据项目之数仓相关知识

第1章 数据仓库概念 数据仓库&#xff08;DW&#xff09;: 为企业指定决策&#xff0c;提供数据支持的&#xff0c;帮助企业&#xff0c;改进业务流程&#xff0c;提高产品质量等。 DW的输入数据通常包括&#xff1a;业务数据&#xff0c;用户行为数据和爬虫数据等 ODS: 数据…

十二届蓝桥杯省赛c++(下)

1、 拿到题目一定要读懂题意&#xff0c;不要看到这题目就上来模拟什么闰年&#xff0c;一月的天数啥的。这个题目问你当天的时间&#xff0c;就说明年月日跟你都没关系&#xff0c;直接无视就好了。 #include <iostream> #include <cstring> #include <algori…

Nginx 教程-动静分离

一、Nginx 动静分离理论1、概念今天学习和梳理Nginx动静分离&#xff0c;动静分离是将网站静态资源&#xff08;HTML&#xff0c;JavaScript&#xff0c;CSS&#xff0c;img等文件&#xff09;与后台应用分开部署&#xff0c;之所以要进行动静分离&#xff0c;其一为了提高前端…
最新文章