python迭代器和生成器

我在开始学习python时,最开始看的两本书中并没有介绍迭代器和生成器的相关知识。因为都是基础入门的读物,主要放在介绍python的语法,函数和基础数据上了。
但是在我开始看一本采用python来实现数据科学计算的书时,迭代器和生成器开始出现了。而且搞得我一头雾水。
在python中,基础的数据结构主要包括列表、元组、字典和集合。而一般较为常用的就是列表和字典了。列表的数据结构是线性的,无论是存储还是搜索,其顺序都是从头到尾。其时间复杂度为O(n)。而集合正如其名,与数学概念上的集合类似。其内部是不允许出现相同元素的。其搜索的时间复杂度为O(log n)。而字典是一种非下标索引的非线性数据结构。其索引方式采用键值对的方式。其时间复杂度也为O(log n)。
而python中之所以会出现迭代器和生成器的概念。可能是出于对无限列表的一种妥协。如果我们要表达一个包含所有自然数的列表。那么无论多大的存储空间是都不够用的。因为自然数集合是无限的。而且我们往往只是需要一个表示具有无穷多个元素列表的方式,并且在特定的时候从中找到某个位置上的值。我们并不需要知道所有的“自然数”都是什么 。为此python提供了一个很棒的方法来实现——迭代器。
我在查找迭代器的资料时,找到的最多的关于迭代器的解释,其实也就是其定义如下:
一个实现了iter方法的对象是可迭代的,一个实现next方法的对象是迭代器。可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
这里有两个概念:可迭代的(Iterated),迭代器(Iterator)
可能直接看定义会让人更加头晕。就像数学里的那些定义和定理。数学家们要的是用最精简的语言来完成最严谨的论述。但是牺牲的是直观性。为了能直观的理解迭代器,抛开这些定义。从问题的根本和实例来理解,然后再把理解到的和定义结合起来。这本来应该是学习该有的样子,而国内的教材和课程。。。
之前我们说过,迭代器可以解决无限列表的表示问题。因此迭代器也要能在需要时计算出列表中的某个元素。如果已经可以将某个无限列表表示为迭代器对象。那么只要调用该对象的next()方法就可以获取迭代器的下一个元素。因此凡是实现了该方法的可迭代对象就都是迭代器。
例如代码:

list = iter([x for i in range(100)])
 for i in list:
     print (next(lsit))
 

其中,iter方法将一个列表转换为一个迭代器。那么就可以采用next()方法访问其下一个元素了。但是可以看到我们上面只是将一个有限列表转化为一个迭代器而已。而我们本来是想要通过迭代来实现无限列表的表示和操作。因此我们实际上我们需要自定义迭代器:

class MyNumbers:
  def __iter__(self):
    self.a = 0
    return self
 
  def __next__(self):
    x = self.a
    self.a += 1
    return x
 
myclass = MyNumbers()
myiter = iter(myclass)
 
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

可以看到在上面的代码中,我们定义了一个类Mynumber,在该类里实现了__iter__()方法和__next__方法。因此该类是一个迭代器类。该类的实例化即为迭代器对象。而且这个迭代器对象可以根据其next函数中定义的规则,无限的推导出下一个元素。

而基本的数据结构的类中,例如list和dict是没有定义next方法的,但是定义了iter方法。因此其是可以迭代的,或者更直白的说是可以循环的。也就是说可以使用for in 语句来实现遍历的。而采用iter(list)可以将可迭代的基本数据结构变为迭代器。虽然我并没有看出这样做的必要。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值