本文概述
迭代器是Python无所不在的精神。它们无处不在, 你必须在某个程序或另一个程序中遇到它们。迭代器是使你可以遍历集合的所有元素的对象, 无论其具体实现如何。
这意味着, 如果你曾经使用循环来迭代或遍历容器中的值, 那么你将使用迭代器。
在本文中, 你将了解有关Python迭代器的更多信息。更具体地说, 你将
- 首先, 你将详细了解Iterators, 以真正了解它们的含义以及何时使用它们。
- 然后, 你将看到什么是Iterables, 因为两者之间存在重要区别!
- 接下来, 你将了解容器以及它们如何使用迭代器的概念。
- 然后, 你将看到运行中的Itertools模块。
- 最后, 你将看到Generators并了解生成器表达式, 这基本上是生成器理解。
资料来源:Vincent Driessen撰写的Iterables vs. Iterators vs. Generators
请务必查看srcmini的两部分Python数据科学工具箱课程。第二部分将通过迭代器, 循环和列表理解为你服务。接下来是一个案例研究, 你将应用在课程中学到的所有技术:第1部分和第2部分相结合。
现在, 让我们深入研究迭代器…..
迭代器
迭代器是实现迭代器协议的对象(不要惊慌!)。迭代器协议不过是Python中的特定类, 而该类进一步具有__next()__方法。这意味着每次你要求下一个值时, 迭代器都会知道如何计算它。它保留有关正在处理的迭代器的当前状态的信息。当你对其调用next()时, 迭代器将调用下一个值。使用__next __()方法的对象最终是一个迭代器。
迭代器有助于生成更清晰的代码, 因为它们使我们可以处理无限序列, 而不必为每个可能的序列重新分配资源, 从而节省了资源空间。 Python有几个内置的对象, 这些对象实现了迭代器协议, 并且你之前必须已经看过其中的一些对象:列表, 元组, 字符串, 字典甚至文件。 Python中还有很多迭代器, 所有itertools函数都返回迭代器。你将在本教程的后面看到itertools。
可迭代
根据nvie.com的Vincent Driessen所说, “可迭代对象是任何对象, 不一定是可以返回迭代器的数据结构”。它的主要目的是返回其所有元素。可迭代可表示有限和无限的数据源。一个Iterable将直接或间接定义两个方法:__iter __()方法, 该方法必须返回迭代器对象;而__next()__方法则借助它调用的迭代器。
注意:通常, 可迭代类将在同一类中同时实现__iter __()和__next __(), 并具有__iter __()返回self, 这使_iterable_类既可迭代, 又具有自己的迭代器。不过, 最好返回一个不同的对象作为迭代器。
什么是迭代器和什么是迭代器之间存在很大的不同。这是一个例子:
a_set = {1, 2, 3}
b_iterator = iter(a_set)
next(b_iterator)
type(a_set)
type(b_iterator)
在该示例中, a_set是一个可迭代的(集合), 而b_iterator是一个迭代器。它们都是Python中不同的数据类型。
想知道当被询问时, 迭代器如何在内部工作以产生下一个序列吗?让我们构建一个返回一系列数字的迭代器:
class Series(object):
def __init__(self, low, high):
self.current = low
self.high = high
def __iter__(self):
return self
def __next__(self):
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current - 1
n_list = Series(1, 10)
print(list(n_list))
__iter__返回迭代器对象本身, 而__next__方法返回迭代器的下一个值。如果没有其他要返回的项目, 则会引发StopIteration异常。
如果你目前无法自己为迭代器编写代码, 那将是很好的选择, 但重要的是你必须掌握其背后的基本概念。你将在本教程的后面部分看到生成器, 这是实现迭代器的一种简单得多的方法。
容器
容器是保存数据值的对象。它们支持成员资格测试, 这意味着你可以检查容器中是否存在值。容器是可迭代的-列表, 集合, 字典, 元组和字符串都是容器。但是还有其他可迭代项, 例如打开文件和打开套接字。你可以对容器执行成员资格测试:
if 1 in [1, 2, 3]:
print('List')
if 4 not in {1, 2, 3}:
print('Tuple')
if 'apple' in 'pineapple':
print('String') #string contains all its substrings
List
Tuple
String
Itertools模块
Itertools是一个内置的Python模块, 其中包含创建用于高效循环的迭代器的函数。简而言之, 它提供了许多与迭代器一起使用的有趣工具!有些会持续提供无限范围的值, 因此只能由实际上停止最终要求更多值的函数或循环访问它们。
让我们检查一下itertools模块中的count函数可以完成的一些有趣的事情:
from itertools import count
sequence = count(start=0, step=1)
while(next(sequence) <= 10):
print(next(sequence))
1
3
5
7
9
11
from itertools import cycle
dessert = cycle(['Icecream', 'Cake'])
count = 0
while(count != 4):
print('Q. What do we have for dessert? A: ' + next(dessert))
count+=1
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
你可以在此处进一步了解itertools。
生成器
生成器是迭代器的精巧兄弟, 它使你可以像以前看到的那样编写迭代器, 但是使用的语法要简单得多, 无需使用__iter __()和__next __()方法编写类。
还记得你先前在迭代器中看到的示例吗?让我们尝试使用生成器的概念来重写代码:
def series_generator(low, high):
while low <= high:
yield low
low += 1
n_list = []
for num in series_generator(1, 10):
n_list.append(num)
print(n_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
生成器的魔咒是收益。函数series_generator中没有return语句。该函数的返回值实际上将是一个生成器。当执行到达yield语句时, 在while循环内, 将返回low的值, 并暂停生成器状态。在第二个下一个调用期间, 生成器从其较早停止处的值恢复, 并将该值增加一。它继续while循环, 并再次返回yield语句。
yield基本上代替了函数的return语句, 而是在不破坏局部变量的情况下向其调用者提供了结果。因此, 在下一次迭代中, 它可以再次处理此局部变量值。因此, 与你之前看到的普通函数不同, 在每次调用时, 它以一组新的变量开始-生成器将在中断处重新开始执行。
提示:惰性工厂是生成器和迭代器背后的概念。这意味着它们一直闲置, 直到你要求输入值为止。只有在被询问时, 他们才能开始工作并产生单个值, 然后它再次变为空闲状态。这是处理大量数据的好方法。如果你不需要一次获取所有数据, 因此无需将所有数据加载到内存中, 则可以使用生成器或迭代器, 这些生成器或迭代器将一次向你传递每个数据。
生成器类型
生成器在Python中可以有两种不同的类型:生成器函数和生成器表达式。
生成器函数是关键字yield出现在体内的函数。你已经使用series_generator函数看到了一个示例。这意味着关键字yield的出现足以使该函数成为生成器函数。
生成器表达式与列表推导等效。对于有限的用例, 它们可能特别有用。就像列表推导会返回列表一样, 生成器表达式也会返回生成器。
让我们看看这意味着什么:
squares = (x * x for x in range(1, 10))
print(type(squares))
print(list(squares))
<class 'generator'>
[1, 4, 9, 16, 25, 36, 49, 64, 81]
生成器的力量是极端的。它们具有更高的内存和CPU效率, 并允许你编写较少中间变量和数据结构的代码。它们通常需要较少的代码行, 其用法使代码更易于阅读和理解。这就是为什么尽可能在代码中使用生成器(Iterables vs. Iterators vs. Generators)很重要的原因。
你可以在代码的哪里插入生成器?提示:在代码中找到执行以下操作的位置:
def some_function():
result = []
for ... in ...:
result.append(x)
return result
并替换为:
def iterate_over():
for ... in ...:
yield x
干得好, Pythonista!
迭代器是Python中强大而有用的工具。但是, 并不是每个人都对它的实质内容非常熟悉。恭喜你完成本教程的结尾!
前往srcmini的数据科学中级Python课程。本教程与matplotlib的功能配合使用, 可用于可视化真实数据。你还将了解新的数据结构, 例如字典和Pandas DataFrame。你已经了解了如何在后台使用迭代器……直接了解Python中的逻辑, 控制流和循环的更多信息。
本教程使用以下内容作为源, 将其检出以了解有关迭代器的更多信息。
- 文森特·德里森(Vincent Driessen)撰写的Iterables vs.Iterators vs.Generators
- 迭代器, 生成器和装饰器
评论前必须登录!
注册