python 面试生成器和迭代器_Python 中的迭代器与生成器

导读

这篇文章主要介绍了 python 当中的迭代器与生成器,在涉及到大数量的场景应该考虑使用迭代器与生成器。

原文链接: https://russellgao.cn/python-iter/

可迭代对象

如果一个对象实现了 __iter__ 方法,那么我们就称它是一个可迭代对象。如果没有实现 __iter__ 而实现了 __getitem__ 方法,并且其参数是从0开始索引的,这种对象也是可迭代的,比如说序列。

使用 iter 内置函数可以获取迭代器的对象,当解释器需要迭代对象时,会自动调用 item(x) :

如果对象实现了 __iter__ 方法,获取一个迭代器

如果没有实现 __iter__ ,但是实现了 __getitem__ ,python 会创建一个迭代器,尝试从索引0开始获取元素

如果获取失败,则抛出 TypeError

标准序列都实现了 __iter__ 方法,所以标准序列都是可迭代对象。如 list,dict,set,tuple。

只有实现了 __iter__ 方法的对象能通过子类测试issubclass(Object,abc.Itertor)

检查对象能否迭代最标准的方法是调用 iter() 函数,因为 iter() 会考虑到实现 __getitem__ 方法的部分可迭代对象。

迭代器

迭代器主要用于从集合中取出元素,那么是什么迭代器呢?

实现了 next 方法的可迭代对象就是迭代器。

next 返回下一个可用的元素,当没有元素时抛出 StopIteration 异常。

__iter__ ,迭代器本身。

到这里应该可以看出「可迭代对象」与 「迭代器」的区别了,就是在于有没有实现next 方法 。

检查对象是不是一个迭代器 :isinstance(object,abc.Iterator) 。

迭代器模式

按需一次获取一个数据项。

迭代器模式的用途有:

访问一个聚合对象而无需暴露它的内部结构

支持对聚合对象的多种遍历

为遍历不同的聚合结构提供一个统一的接口

说了这么多,那么除了标准序列之外,如何自定义一个迭代器呢,看看下面的代码:

class Books:

def __init__(self, books):

self.books = books.split(",")

def __iter__(self):

return BookIterator(self.books)

class BookIterator:

def __init__(self, books):

self.books = books

self.index = 0

def next(self):

try :

book = self.books[self.index]

except IndexError:

raise StopIteration()

self.index += 1

return book

def __iter__(self):

return self

books = Books("python,golang,vue,kubernetes,istio")

print(books)

for book in books :

print(book)

生成器

生成器是一种特殊的迭代器,这种迭代器更加优雅,不需要像上面一样写 __iter__ 和 next 方法了,只需要一个 yield 关键字即可。

生成器有两种方法用:

yield

() 生成

yield

def gen(x) :

for i in range(x) :

yield i * 2

g1 = gen(10)

() 生成器

l1 = [ i * 2 for i in range(10) ]

g1 = (i * 2 for i in range(10))

for i in g1 :

print(i)

print(l1)

l1 是一个列表推导式

g1 是一个生成器

两者的区别是 g1 生成器采用懒加载的方式,不会一次把数据加载到内存中

生成器的好处不用把数据全部加载到内存中,访问到的时候在计算出来。例如有 100w 的数据集,但是只需要访问前 100 个,是不是生成器就很有用了。

特别说明

上述写法为 python2 的写法,python3 略有不同,python3 中 next 方法对应的为 __next__ ,如上面的 Books 例子对应的写法为:

class Books:

def __init__(self, books):

self.books = books.split(",")

def __iter__(self):

return BookIterator(self.books)

class BookIterator:

def __init__(self, books):

self.books = books

self.index = 0

def __next__(self):

try :

book = self.books[self.index]

except IndexError:

raise StopIteration()

self.index += 1

return book

def __iter__(self):

return self

books = Books("python,golang,vue,kubernetes,istio")

print(books)

for book in books :

print(book)

总结

任何对象只要实现了 __iter__ 方法就是一个可迭代对象

任何对象只要实现了 __iter__ 和 next 方法就是一个迭代器

生成器是一个特殊的迭代器,可以通过 yield 和 () 的方式生成

在数据量大的时候使用会有奇效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值