首页 > 编程语言 >6.Python3 迭代器与生成器

6.Python3 迭代器与生成器

时间:2024-03-05 13:45:35浏览次数:33  
标签:__ 迭代 对象 生成器 iter next Python3

Python3 迭代器与生成器

1.迭代器

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器

迭代器的定义

  • 字面意思:更新迭代,器:工具:可更新迭代的工具。
  • 专业角度:内部含有'__iter__'方法并且含有'__next__'方法的对象就是迭代器。
  • 可以判断是否是迭代器:'__iter__' and '__next__' 在不在dir(对象)

当我们遇到可迭代对象但想将它当作迭代器使用时可以使用iter()方法转化。

li_=iter(li)
print(type(li_))
#输出为“list_iterator",即已经转换为迭代器。

可迭代对象

  • 字面意思:可以进行循环更新的一个实实在在值。
  • 专业角度: 内部含有'__iter__'方法的对象,可迭代对象。
  • 判断一个对象是不是可迭代对象: '__iter__' in dir(对象)

迭代器和可迭代对象的区别

  • 如果定义类时,有__iter__方法,那么这个类创建出来的对象一定是可迭代对象。
  • 迭代器有两个基本的方法:iter()next(),一个实现了__iter__方法和__next__方法的对象,就是迭代器。
  • 迭代器对象 一定是 可迭代对象;可迭代对象 不一定是 迭代器;因此迭代器中包括可迭代对象没有的属性和方法,比如__next__()。

字符串,列表或元组对象(可迭代对象)都可用于创建迭代器(转换为迭代器):

list=[1,2,3,4]
it = iter(list)    # iter()获取一个可迭代对象的迭代器
print (next(it))   # next()获取迭代器的数据
print (next(it))
# 输出 1 2

# 迭代器对象可以使用常规for语句进行遍历:
list=[1,2,3,4]
it = iter(list)    # 创建迭代器对象
for x in it:
    print (x, end=" ")
# 输出 1 2 3 4

创建一个迭代器(自定义迭代器)

把一个类作为一个迭代器使用需要在类中实现两个方法 iter() 与 next() 。iter() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。next() 方法会返回下一个迭代器对象。

创建一个返回数字的迭代器,初始值为 1,逐步递增 1,StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self
 
  def __next__(self):
    if self.a <= 5:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration
 
myclass = MyNumbers()
myiter = iter(myclass)
 
for x in myiter:
  print(x)

执行输出结果为:

1
2
3
4
5

2.生成器

在 Python 中,使用了 yield 的函数被称为生成器(generator)。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,并返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。

以下实例使用 yield 实现斐波那契数列:

#!/usr/bin/python3
 
import sys
 
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()0 1 1 2 3 5 8 13 21 34 55

执行以上程序,输出结果如下:

0 1 1 2 3 5 8 13 21 34 55
  1. yield ayield 是 Python 中一个非常有用的关键字,它用于定义生成器函数并返回生成器对象。当生成器函数执行到 yield 关键字时,它将将当前函数状态保存为暂停状态,并向调用方返回一个值 a,之后程序流程将被挂起,直到下次通过 next() 函数调用该生成器对象时再恢复执行状态。在斐波那契数列生成器函数中,每次执行到 yield a 时,都会生成当前数列的第一个数字 a 并返回给调用方。
  2. a, b = b, a + b: 这是 Python 中的一种元组赋值语法,可以同时将多个变量赋值为多个值。在斐波那契数列生成器函数中,这行代码的作用是更新相邻两个数字 ab 的值,以便生成下一个斐波那契数。首先,变量 a 被赋值为变量 b 的值,表示将上一个斐波那契数列中的第二个数字赋值为下一个数列的第一个数字;然后,变量 b 被赋值为表达式 a + b 的值,表示将上一个斐波那契数列中的前两个数字相加得到下一个数列中的第二个数字。这样,在每次执行 yield a 之前,都会先更新 ab 的值,从而生成下一个斐波那契数。

示例一

一个函数 f,f 返回一个 list,这个 list 是动态计算出来的(不管是数学上的计算还是逻辑上的读取格式化),并且这个 list 会很大(无论是固定很大还是随着输入参数的增大而增大),这个时候,我们希望每次调用这个函数并使用迭代器进行循环的时候一个一个的得到每个 list 元素而不是直接得到一个完整的 list 来节省内存,这个时候 yield 就很有用。

以斐波那契函数为例,我们一般希望从 n 返回一个 n 个数的 list:

def fab(max): 
   n, a, b = 0, 0, 1 
   L = [] 
   while n < max: 
       L.append(b) 
       a, b = b, a + b 
       n = n + 1 
   return L

上面那个 fab 函数从参数 max 返回一个有 max 个元素的 list,当这个 max 很大的时候,会非常的占用内存。

一般我们使用的时候都是这个样子的,比如:

f = iter(fab(1000))
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

这样我们实际上是先生成了一个 1000 个元素的 list:f,然后我们再去使用这个 f。

现在,我们换一个方法:

因为我们实际使用的是 list 的遍历,也就是 list 的迭代器。那么我们可以让这个函数 fab 每次只返回一个迭代器——一个计算结果,而不是一个完整的 list:

def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b 
        # print b 
        a, b = b, a + b 
        n = n + 1 

这样,我们每次调用fab函数,比如这样:

for x in fab(1000):
    print(x)

或者 next 函数之类的,实际上的运行方式是每次的调用都在 yield 处中断并返回一个结果,然后再次调用的时候再恢复中断继续运行。

3.迭代器与生成器区别

迭代器和生成器算是 Python 一大特色,其核心是基于迭代器协议来的。

而平时我们经常使用的 for in 循环体,本质就是迭代器协议的一大应用。

同时 Python 内置的集合类型(字符、列表、元组、字典)都已经实现了迭代器协议,所以才能使用 for in 语句进行迭代遍历。for in 循环体在遇到 StopIteration 异常时,便终止迭代和遍历。

再说下可迭代、迭代器、生成器三个概念的联系和区别。

1、可迭代概念范围最大,生成器和迭代器肯定都可迭代,但可迭代不一定都是迭代器和生成器,比如上面说到的内置集合类数据类型。可以认为,在 Python 中,只要有集合特性的,都可迭代。

2、迭代器,迭代器特点是,均可以使用 for in 和 next 逐一遍历。

3、生成器,生成器一定是迭代器,也一定可迭代。

4.for…in… 循环的本质

1.先调用 iter()函数,它会自动调用可迭代对象中的 __iter__方法,此方法返回这个可迭代对象的 迭代器对象

2.对获取到的迭代器不断调用 next()函数,它会自动调用迭代器中的 __next__方法来获取下一个值

3.当遇到 StopIteration异常后循环结束

4.for 循环可以迭代任何可迭代对象。

标签:__,迭代,对象,生成器,iter,next,Python3
From: https://www.cnblogs.com/littlecamel/p/18053860

相关文章

  • 5.Python3 推导式
    Python3推导式推导式(comprehensions),又称解析式,是Python中常见的语法糖。推导式可以从一个数据序列构建另一个新的数据序列,常用于数据处理场景。表达式for迭代变量in可迭代对象[if条件表达式]其中if条件判断根据需要,可有可无。Python支持各种数据结构的推导式:列......
  • 4.Python3 运算符
    Python3运算符1.Python算术运算符以下假设变量a=10,变量b=21:运算符描述实例+加-两个对象相加a+b输出结果31-减-得到负数或是一个数减去另一个数a-b输出结果-11*乘-两个数相乘或是返回一个被重复若干次的字符串a*b输出结果210/除......
  • 9.Python3 面向对象
    Python3面向对象1.类定义Python中定义一个类使用class关键字实现,其基本语法格式如下:classClassName:<statement-1>...<statement-N>类实例化后,可以使用其属性,创建一个类之后,可以通过类名访问其属性。无论是属性还是方法,对于类来说,它们都不是......
  • 8.Python3 模块和包
    Python3模块和包为此Python提供了一个办法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件被称为模块。模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用python标准库的方法......
  • python3.6.8 安装解决ssl问题
    https://www.cnblogs.com/mqxs/p/9103031.html#!/bin/bashecho"正在安装相关组件"yuminstall-yopenssl-develbzip2-develexpat-develgdbm-develreadline-develsqlite-develgcc-c++gccopenssl-develecho"下载安装包"wgethttps://www.python.org/ft......
  • centos7 安装python3.8
    #cd/usr/local#yum-ygroupinstall"Developmenttools"#yum-yinstallzlib-develbzip2-developenssl-develncurses-develsqlite-develreadline-develtk-develgdbm-develdb4-devellibpcap-develxz-devel#yuminstalllibffi-devel-ywgethttps:/......
  • 动手学强化学习(五):值迭代与策略迭代代码
    一、策略迭代importcopyclassCliffWalkingEnv:"""悬崖漫步环境"""def__init__(self,ncol=12,nrow=4):self.ncol=ncol#定义网格世界的列self.nrow=nrow#定义网格世界的行#转移矩阵P[state][action]=[(p,next_state,......
  • 迭代器
    迭代器fromcollections.abcimportIterator,Iterable3.8版本以上迭代器是能被next()函数调用并不断返回下一个值的对象。迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次的结果而继续的。迭代器的特征是并不依赖索引,而通过next指针(内存地址寻址)迭......
  • Centos 上python3 pip3安装报错:WARNING: pip is configured with locations that requ
    pip3安装报错:WARNING:pipisconfiguredwithlocationsthatrequireTLS/SSL,howeverthesslmoduleinPythonisnotavailable.在网上查一下原因是openssl版本不兼容导致,centos默认带的openssl版本太低,要升级openssl版本。openssl  下载地址:https://www.openssl.org/s......
  • Centos 上安装python3
    1、yum方式安装: 查看yum的python可安装包yumsearchpython安装指定的python版本yuminstallpython3.x86_64-y安装完成:查看安装包的信息:rpm-qa|greppython3 2、编辑安装:下载地址:https://www.python.org/ftp/python/3.11.8/Python-3.11.8.tgz解压......