干货推荐:Python迭代器和生成器最易懂、最全面的文章

迭代器与可迭代对象

概念

迭代器:是访问数据集合内元素的一种方式,一般用来遍历数据,但是他不能像列表一样使用下标来获取数据,也就是说迭代器是不能返回的。

Iterator:迭代器对象,必须要实现 next 魔法函数

Iterable:可迭代对象,继承 Iterator,必须要实现 iter 魔法函数

比如:

from collections import Iterable,Iterator
a = [1,2,3]
print(isinstance(a,Iterator))
print(isinstance(a,Iterable))

返回结果

False
True

在 Pycharm 中使用 alt+b 进去 list 的源码中可以看到,在 list 类中有 iter 魔法函数,也就是说只要实现了 iter 魔法函数,那么这个对象就是可迭代对象。

上面的例子中 a 是一个列表,也是一个可迭代对象,那么如何才能让这个 a 变成迭代器呢?使用 iter() 即可。

from collections import Iterable,Iterator
a = [1,2,3]
a = iter(a)
print(isinstance(a,Iterator))
print(isinstance(a,Iterable))
print(next(a))
print('----')
for x in a:
    print(x)

返回结果

True
True
1
----
2
3

可以看到现在 a 是可迭代对象又是一个迭代器,说明列表 a 中有 iter 方法,该方法返回的是迭代器,这个时候使用 next 就可以获取 a 的下一个值,但是要记住迭代器中的数值只能被获取一次。

梳理迭代器 (Iterator) 与可迭代对象 (Iterable) 的区别:

可迭代对象:继承迭代器对象,可以用 for 循环(说明实现了 iter 方法)

迭代器对象:可以用 next 获取下一个值(说明实现了 next 方法),但是每个值只能获取一次,单纯的迭代器没有实现 iter 魔法函数,所以不能使用 for 循环

只要可以用作 for 循环的都是可迭代对象

只要可以用 next() 函数的都是迭代器对象

列表,字典,字符串是可迭代对象但是不是迭代器对象,如果想变成迭代器对象可以使用 iter() 进行转换

Python 的 for 循环本质上是使用 next() 进行不断调用,for 循环的是可迭代对象,可迭代对象中有 iter 魔法函数,可迭代对象继承迭代器对象,迭代器对象中有 next 魔法函数

一般由可迭代对象变迭代器对象

大家在学python的时候肯定会遇到很多难题,以及对于新技术的追求,这里推荐一下我们的Python学习扣qun:784758214,这里是python学习者聚集地!!同时,自己是一名高级python开发工程师,从基础的python脚本到web开发、爬虫、django、数据挖掘等,零基础到项目实战的资料都有整理。送给每一位python的小伙伴!每日分享一些学习的方法和需要注意的小细节

可迭代对象

可迭代对象每次使用 for 循环一个数组的时候,本质上会从类中尝试调用 iter 魔法函数,如果类中有 iter 魔法函数的话,会优先调用iter魔法函数,当然这里切记 iter 方法必须要返回一个可以迭代的对象,不然就会报错。

如果没有定义 iter 魔法函数的话,会创建一个默认的迭代器,该迭代器调用 getitem 魔法函数,如果你没有定义 iter 和 getitem 两个魔法函数的话,该类型就不是可迭代对象,就会报错。

比如:

class s:
    def __init__(self,x):
        self.x = x
    def __iter__(self):
        return iter(self.x)
        # 这里必须要返回一个可以迭代的对象
    # def __getitem__(self, item):
    #     return self.x[item]
# iter和getitem其中必须要实现一个
a = s('123')
# 这里的a就是可迭代对象
# 这里不能调用next(a)方法,因为没有定义
for x in a:
    print(x)

这里把注释符去掉返回结果也是一样的,返回结果:

迭代器对象

一开始提起,iter 搭配 Iterable 做可迭代对象,next 搭配 Iterator 做迭代器。next() 接受一个迭代器对象,作用是获取迭代器对象的下一个值,迭代器是用来做迭代的,只会在需要的时候产生数据。

和可迭代对象不同,可迭代对象一开始是把所有的列表放在一个变量中,然后用 getitem 方法不断的返回数值,getitem 中的 item 就是索引值。

但是 next 方法并没有索引值,所以需要自己维护一个索引值,方便获取下一个变量的位置。

class s:
    def __init__(self,x):
        self.x = x
        # 获取传入的对象
        self.index = 0
        # 维护索引值
    def __next__(self):
        try:
            result = self.x[self.index]
            # 获取传入对象的值
        except IndexError:
            # 如果索引值错误
            raise StopIteration
        # 抛出停止迭代
        self.index += 1
        # 索引值+1,用来获取传入对象的下一个值
        return result
        # 返回传入对象的值

a = s([1,2,3])
print(next(a))
print('----------')
for x in a:
# 类中并没有iter或者getitem魔法函数,不能用for循环,会报错
    print(x)

返回结果

Traceback (most recent call last):
1
----------
  File "C:/CODE/Python进阶知识/迭代协议/迭代器.py", line 34, in <module>
    for x in a:
TypeError: 's' object is not iterable

上面一个就是完整的迭代器对象,他是根据自身的索引值来获取传入对象的下一个值,并不是像可迭代对象直接把传入对象读取到内存中,所以对于一些很大的文件读取的时候,可以一行一行的读取内容,而不是把文件的所有内容读取到内存中。

生成器

生成器:函数中只要有 yield,这个函数就会变成生成器。每次运行到 yield 的时候,函数会暂停,并且保存当前的运行状态,返回返回当前的数值,并在下一次执行 next 方法的时候,又从当前位置继续往下走。

简单用法

举个例子:

def gen():
    yield 1
    # 返回一个对象,这个对象的值是1
def ret():
    return 1
    # 返回一个数字1
g = gen()
r = ret()
print(g,r)
print(next(g))

返回结果

<generator object gen at 0x000001487FDA2D58> 1
1

来源:PY学习网:原文地址:https://www.py.cn/article.html

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » 干货推荐:Python迭代器和生成器最易懂、最全面的文章