python中的迭代器

这篇具有很好参考价值的文章主要介绍了python中的迭代器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

⛳ 目录

  • 什么是迭代器
  • 如何生成迭代器
  • 迭代器的用法

🎈迭代器和可迭代对象

迭代器是为了给迭代对象进行迭代使用的。迭代也就是遍历,可以从头到尾的遍历所有的元素。列表、集合、元组、字典、字符串、都是可迭代对象。如果一个对象拥有_iter方法,其是可迭代对象。

🎈生成器

  • 生成器(Generator)在 Python 中具有许多有用的作用和优势,包括:
  1. 惰性计算(Lazy Evaluation):生成器使用惰性计算的方式逐个生成值。它们不会一次性生成所有值,而是按需生成,节省了内存和计算资源。这对于处理大型数据集或无限序列特别有用。

  2. 延迟执行(Lazy Execution):生成器的执行是逐步的,只在需要时才会执行代码。这种延迟执行的特性使得生成器非常适合处理耗时的操作,避免了一次性计算所有结果。

  3. 迭代器协议支持:生成器自动实现了迭代器协议,因此它们可以被 for 循环等迭代工具直接使用。这使得生成器可以方便地进行迭代遍历,无需额外的代码。

  4. 内存效率:生成器不需要存储所有生成的值,而是在需要时按需生成。这使得生成器非常适合处理大型或无限序列,因为它们节省了内存资源。

  5. 状态维护:生成器函数可以维护局部变量和状态,通过 yield 语句可以保存函数的执行状态,并在下一次调用时恢复执行。这使得生成器可以实现复杂的迭代逻辑、状态机和协程等。

  6. 数据流处理:生成器可以用于处理连续的数据流,逐个处理数据并生成结果。这对于处理实时数据或流式数据非常有用,可以逐步处理数据而无需等待所有数据到达。

  7. 管道和链式操作:生成器可以通过管道和链式操作组合在一起。一个生成器的输出可以作为另一个生成器的输入,从而实现数据流的处理和转换。

总的来说,生成器提供了一种高效、灵活和内存友好的方式来处理迭代和序列生成。它们可以用于处理大数据集、实现延迟计算、处理数据流、实现协程等各种场景。通过生成器,可以以优雅而高效的方式处理迭代逻辑,减少内存占用,并提高代码的可读性和可维护性。

🎈什么是迭代器

  • 迭代器(Iterator)是一种特殊的对象,它可以在遍历时逐个返回元素。迭代器实现了迭代协议,包括两个重要的方法:
  1. __iter__() 方法:返回迭代器对象自身。
  2. __next__() 方法:返回迭代器的下一个元素,如果没有元素可供返回,则抛出 StopIteration 异常。

迭代器对象可以通过调用内置的 iter() 函数来获取,它可以应用于可迭代对象(如列表、元组、字符串等)或自定义的实现了 __iter__() 方法的对象。

  • 按需加载,有一点内容就放入内存一点
  • 无需等待所有内容加载到内存中才使用,提升效率
  • 在说什么是迭代器之前,我们来举一个例子。首先有请我们的小木同学。小木同学想去超市买苹果,到了超市,看到超市中有苹果的柜台。不过柜台上销售员正在摆放苹果,小木同学要等到销售员摆放苹果完毕之后才可以拿。这就很耽误小木同学的时间。其实。柜台上已经有苹果了,但是销售不让拿,非要等到全部摆放完成之后才可以。接下来第二天,小木同学又来超市买苹果。这次的销售员很好说话,他说,我可以一边摆放苹果,一边让小木来拿。这样就可以很好的节省小木同学的时间,如果小木同学拿苹果的速度超过了销售员摆放的速度,小木同学只需要等待一会儿,只要销售员摆放一个苹果,小木同学就可以立即拿到。这样大大增加了小木同学买苹果的效率。迭代器就类似于后者。
  • 我们平时的程序。都是一次性写入到内存中,比如我们的列表有100或者1000甚至1万个数据,都是一次性写入到内存里的,通过这样让我们来使用。但是迭代器是按需加载,有一点内容就放到内存里一点,我们就可以立刻使用内存中的一点数据进行逻辑处理。这样就不需要等待所有的内容都写到内存中,我们就可以使用,大大提升了效率。

🎈如何生成迭代器-iter

  • 介绍:

    • 生成一个迭代器对象
  • 用法:

    • iter(iterable)
    • 我们将iter函数中传入一个列表,它会返回一个列表的迭代器对象。生成迭代器对象之后,我们将使用这个迭代器对象。通过Python的内置函数。就可以将迭代器对象中的数据进行返回。我们来看一下用法。我们只需要调用next函数,将迭代器对象作为参数传入。只要我们的迭代器对象当中有数据,我们可以一直调用next函数。用法有些类似于我们的文件对象读取的readline函数,我们来看一个例子。我们定义了一个迭代器对象
  • 参数介绍:

    • iterable :可迭代的数据类型
  • 举例:

    • iter([1, 2, 3])
  • 返回值:

    • < list_ iterator at 0x4f3aee0>

🎈迭代器的使用-next

  • 介绍:
    • 返回迭代器中数据
    • 我们每使用一次next函数,就会返回迭代器中的一个值
    • 比如括弧里边传入的是一个列表。看似我们将这个列表所有的内容都放到迭代器里,实际上则不然。当我们每调用一次next的时候,我们才会把列表中的一个元素放到内存中,由next去读取。所以我们的iter并没有一次性的把列表中的数据全部放到迭代器中,这就是我们说的按需加载。
      -迭代器对象中的数据全部调用完毕,再次调用next函数,程序就会直接报个错误。
  • 用法:
    • next(iterator)
  • 参数介绍:
    • iterator :迭代器对象
  • 举例:
    • iter_ obj = iter([1,2,3])
    • next(iter_obj)
  • 返回值:
    • 1, 2 ,3
    • StopIteration

🎈迭代器常用方法之生成迭代器

  1. for循环生成法一yield
    • yield 是一个关键字,用于定义生成器函数(Generator Function)
    • 生成器函数是一种特殊的函数,它在执行时会生成一个可迭代的对象,通过逐步生成值的方式,而不是一次性生成所有值的方式。生成器函数使用 yield 语句来定义生成器的每个值,并在生成器中暂停和恢复执行。
    • 以下是生成器函数的语法示例:
def my_generator():
    # 生成器函数的逻辑
    yield value1
    yield value2
    # ...
  • 在生成器函数中,每个 yield 语句都会将一个值生成给调用者,并且函数的执行会在此处暂停。调用者可以通过迭代生成器对象来获取生成器函数产生的值。每次迭代,生成器函数会从上一次暂停的位置恢复执行,并生成下一个值。

  • 以下是一个简单的生成器函数示例,生成斐波那契数列的前n个数字:

def fibonacci(n):
    a, b = 0, 1
    count = 0
    while count < n:
        yield a
        a, b = b, a + b
        count += 1

# 使用生成器函数生成斐波那契数列的前10个数字
fib_gen = fibonacci(10)
for num in fib_gen:
    print(num)
  • 生成器函数 fibonacci 使用 yield 语句生成每个斐波那契数列的数字。在每次迭代中,生成器函数会在 yield 处暂停,并返回生成的值。在 for 循环中,我们迭代生成器对象 fib_gen,每次迭代都会从上一次暂停的位置恢复执行,并生成下一个斐波那契数。

  • 生成器表达式可以直接生成一个生成器对象,而不需要定义生成器函数。

总结起来,yield 关键字用于定义生成器函数中,它允许逐步生成值的方式来创建生成器。通过 yield,可以在生成器函数中暂停和恢复执行,并向调用者提供生成的值。这种逐步生成值的方式在处理大量数据或需要延迟计算的情况下非常有用。

  • 我们先看第一种。我们可以在函数中使用for循环。并对每一个for循环的成员都要用yield的函数。它的意思就是将for循环中的每个成员放到一个迭代器对象中。不过只有被调用才会被放入,我们来看例子。我们看到这个例子。其中在定义了一个test函数里边使用for循环。我们将每个循环的成员通过yield放到迭代器中。当然,就像我们刚才说的,只有在调用next函数的时候,for循环的成员才会通过yield关键字放到迭代器中被next调用。这就是按需加载的意思。
In [27]: def test():
for i in range(10):
......print(i)
......yield i
In [28]: res = test()
In [29]: next(res)
0ut[29]: 0
  1. for循环一行生成迭代器
    • 第二种方法,我们可以直接使用for循环生成一个迭代器对象。我们来看这样一句话,我们将for循环放到了一行中,我们看for i in[123],这句话和我们定义一般的for循环没有差距,但是本来在for循环代码块中执行的i成员却跑到了for关键字的前面。并且将整个for循环包含for关键字前面的i成员用小括号包裹起来。这就是一个用for循环在非函数中定义迭代器的方法。我们将这个迭代器赋值给变量res,并使用next调用迭代器执行迭代器中的内容。使用for循环生成的迭代器,可以不使用next也可以执行。我们依然可以通过for循环来获取迭代其中的数据。不仅如此,当我们执行调取完迭代器中的数据之后,程序不会抛出异常。相比于next函数要友好的多。
In [30]:res=(i for i in [1,2,3])
In [31]: next(res)
Out [31] : 1

🎈迭代器常用方法之for循环获取

  • 优点:不会报错
In [32]:res=(i for i in [1,2,3])
In [33]: for item in res:
     ...:    print ( item)
1
2
3

PS: 迭代器每一次使用会将其放到内存中,将数据被读取后,内存的数据会被释放,所以当完整读取一个迭代器后,这个迭代器中的内存数据就已经空了,再次执行就拿不到数据了。文章来源地址https://www.toymoban.com/news/detail-715915.html

🎯实战

  • 当抛出了StopIteration这样一个异常.实际上在我们的工作中就必须要去捕获这个异常
  • 首先书写一个封装一层的next函数,我们加一个横杠,_next里边选入我们的iter_obj对象。我们通过try-except来进行捕获,try中我们直接return,我们调用_next,并且把我们的iter生成器传入,然后,我们要用except,在里边我们通过StopIteration声明要捕获的异常类型,我们并不需要将我们的StopIteration起一个别名,因为我们知道它一定会抛什么样的错误。
  • 我们的迭代器会把数据一次一次都放到内存中。当放到内存中并且被读取之后,内存的内容就会被释放,所以我们当完整的读取完一个迭代其对象之后。这个迭代器对象中的内存数据就已经空了。所以我们再去执行就拿不到数据了,请同学们要注意这一点。
  • 除了我们刚才说的按需加载可以提升我们的执行速度以外,还有另外一个原因,想一想。如果我们有一个列表,现在只有十个数据,那么读取速度会很快,可能对资源,也就是说我们的内存占用不会消耗很大。如果我们有一个100亿成员的列表,那么这100亿的数据都要一次性写到内存里。我们想一下这个时间将消耗有多大?不仅如此,一百亿的数据写到内存里,是不是有可能会撑爆我们的内存?因为毕竟我们的内存是有容量限制的。当超过了我们的容量,我们的内存就会溢出,程序就会报错了。所以如果通过迭代器的方式,我们只需要用到一个数据,我们就把这个数据扔到内存里并且被使用,这样子既可以提高效率,又可以节省内存的消耗。这就是我们平时使用迭代器的目的。
#!/user/bin/env python
# -*- coding: utf-8 -*-

iter_obj = iter((1, 2, 3))

def _next(iter_obj):
    try:
        return next(iter_obj)
    except StopIteration:
        return None

# print(_next(iter_obj))
# print(_next(iter_obj))
# print(_next(iter_obj))
# print(_next(iter_obj))  # 当迭代器中数据被调用完后,将不再被调用

for i in iter_obj:
    print(i)
print('========')

def make_iter():
    for i in range(10):
        yield i

iter_obj = make_iter()

for i in iter_obj:
    print(i)
print('---------')
"""
迭代器每一次使用会将其放到内存中,
将数据被读取后,内存的数据会被释放,
所以当完整读取一个迭代器后,这个迭代器
中的内存数据就已经空了,再次执行就拿不
到数据了
"""
for i in iter_obj:
    print(i)

iter_obj = (i for i in range(5))

for i in iter_obj:
    print(i)
print('========')
for i in iter_obj:
    print(i)
1
2
3
========
0
1
2
3
4
5
6
7
8
9
---------
0
1
2
3
4
========

Process finished with exit code 0

到了这里,关于python中的迭代器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python中的迭代器

    什么是迭代器 如何生成迭代器 迭代器的用法 迭代器是为了给迭代对象进行迭代使用的。迭代也就是遍历,可以从头到尾的遍历所有的元素。列表、集合、元组、字典、字符串、都是可迭代对象。如果一个对象拥有_iter方法,其是可迭代对象。 生成器(Generator)在 Python 中具

    2024年02月08日
    浏览(29)
  • 【python全栈开发】面向对象进阶

    实例变量:属于对象,每个对象中各自维护自己的数据。 类变量:属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)。 类变量和实例变量的区别示例: 类变量和实例变量+继承问题: 通常来说,调用的变量不是对象变量时,就会去对应的类中

    2024年02月21日
    浏览(82)
  • 【 Python 全栈开发 - WEB开发篇 - 21 】进程与线程

    进程和线程都是计算机中用来实现多任务并发的机制,但它们有区别和联系。 区别: 定义不同:进程是操作系统分配资源的基本单位,是程序执行时的一个实例,包括代码、数据和资源,可以看成是程序的一次执行过程。而线程是进程内的一个执行单元,是程序执行流的最

    2024年02月08日
    浏览(41)
  • 【 Python 全栈开发 - WEB开发篇 - 26 】Javascript 基础

    Javascript 是一种动态的、基于对象的编程语言,通常用于网页的客户端脚本编程。它可以在网页上实现交互效果、动态效果、表单验证、数据处理等功能。 学习 Javascript 可以通过以下途径: 在线教程:像 w3schools、MDN 等网站提供了详细的 Javascript 教程和示例代码。 书籍:可以

    2024年02月08日
    浏览(38)
  • Python全栈开发(一)——环境搭建和入门

    今天是2023年的第一天,接下来的一个月里,我将持续更新关于python全栈开发的相关知识,前面一段时间都是基础语法。主要分成四大块:基础、面向对象、MYSQL数据库、Django框架。话不多说,进入到今天的主题。 markdown笔记-语法-格式笔记 # 第一章 python基础 ## 1.1 环境搭建 使

    2024年02月03日
    浏览(38)
  • 【 Python 全栈开发 ⑤ 】Python 数据类型与运算符

    Python 中一共有 6 种基本数据类型,他们是: Number(数字) String(字符串) List(列表) Tuple(元组) Set(集合) Dictionary(字典) 在这6个基本数据类型中, 不可变数据 有3个: Number(数字) String(字符串) Tuple(元组) 可变数据 有3个: List(列表) Set(集合) Dictiona

    2024年02月02日
    浏览(48)
  • [开发语言][python][c++]:C++中的this指针和Python中的Self -- 26岁生日

    以朋友的新岁祝福开篇,祝笔者也祝大家☺️: 之前一直对 C++ 中的 this 和 python 中的 self 到底是什么关系,为什么 C++ 要显式的写出来,python 则不需要? 模糊不清,趁着周末整理一下相关结论,希望本篇文章可以解答这些问题,同时对C++和Python中的类加深些理解。 python 当

    2024年01月24日
    浏览(67)
  • Python中的迭代器与生成器

    在Python中,迭代器(Iterator)和生成器(Generator)是两种用于处理可迭代对象的重要工具。而可迭代对象包括列表,元组,字典,字符串等。 迭代器和生成器只能迭代一次,通常用于处理大型数据集,因为它们不会一次性加载所有数据到内存中,而是根据需要逐个生成值。

    2024年02月10日
    浏览(43)
  • 【Rust】Rust学习 第十三章Rust 中的函数式语言功能:迭代器与闭包

    Rust 的设计灵感来源于很多现存的语言和技术。其中一个显著的影响就是  函数式编程 ( functional programming )。函数式编程风格通常包含将函数作为参数值或其他函数的返回值、将函数赋值给变量以供之后执行等等。 更具体的,我们将要涉及: 闭包 ( Closures ),一个可以储

    2024年02月12日
    浏览(51)
  • 【 Python 全栈开发 - 语法基础篇 - 20 】数据可视化

    数据可视化是一种将数据转化成可视化图形的表现形式,目的是更好地展示和交流数据,从而更深层次地理解数据。 这种表现形式通常是基于图表、图形、地图和其他视觉元素,帮助人们识别和理解数据的趋势、模式和异常,以及进行更有效的决策。 数据可视化也是数据科

    2024年02月08日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包