简体   繁体   English

Python 3中的迭代器

[英]Iterators in Python 3

In Python 3 a lot of functions (now classes) that returned lists now return iterables, the most popular example being range . 在Python 3中,许多返回列表的函数(现在是类)现在返回iterables,最常见的例子是range In this case range was made an iterable in Python 3 to improve performance, and memory efficiency (since you don't have to build a list anymore). 在这种情况下,范围在Python 3中是可迭代的,以提高性能和内存效率(因为您不必再​​构建列表)。

Other "new" iterables are map , enumerate , zip and the output of the dictionary operations dict.keys() , dict.values() and dict.items() . 其他“新” iterables是mapenumeratezip和字典操作的输出dict.keys() dict.values()dict.items() (There are probably more, but I don't know them). (可能还有更多,但我不知道)。

Some of them ( enumerate and map ) have become probably more memory efficient by converting them into iterables. 其中一些( enumeratemap )通过将它们转换为迭代可能变得更有效。 In Python 2.7 the others simply created lists of objects which were already in memory, so they would have been memory efficient. 在Python 2.7中,其他人只是创建了已经在内存中的对象列表,因此它们可以提高内存效率。

Why then turn them into iterables which you have to convert to lists every time you want to sort them, etc.? 为什么然后将它们变成可以在每次要对它们进行排序时必须转换为列表的迭代,等等?

Several reasons: 几个原因:

  1. The dictionary operations now return dictionary view objects ; 字典操作现在返回字典视图对象 ; these act as sets as well, giving you a far richer object to work with in your code. 这些也可以作为集合,为您提供更丰富的对象,以便在您的代码中使用。 In Python 2 you'd have to use the dict.view*() methods to do the same. 在Python 2中,你必须使用dict.view*()方法来做同样的事情。

  2. The dictionary operations in Python 2 produced a new list object; Python 2中的字典操作产生了一个新的列表对象; that list object takes up memory too, even if the indices reference existing objects. 即使索引引用现有对象,列表对象也会占用内存。 There is another side effect here; 这里还有另一个副作用; the list indices increment the reference counts on all those dictionary contents, which impacts performance as well (and potentially flush the CPU cache). 列表索引会增加所有这些字典内容的引用计数,这也会影响性能(并且可能会刷新CPU缓存)。

  3. zip() and map() could always work on any iterables, including generators, but would pull everything into a big list when applied. zip()map()总是可以处理任何迭代,包括生成器,但是在应用时会将所有内容都拉到一个大的列表中。 By turning them into generators in Python 3 they no longer auto-consume such iterables. 通过在Python 3中将它们转换为生成器,它们不再自动消耗这样的迭代。

Note that enumerate() in Python 2 never returned a list, it has always returned an iterator. 请注意,Python 2中的enumerate()从未返回过列表,它总是返回一个迭代器。

You can always get the old Python 2 behaviour simply by applying list() on such objects. 只需在这些对象上应用list()就可以始终获得旧的Python 2行为。 If you needed sorted items, you'd call sorted() on the iterable. 如果你需要排序的项目,你可以在iterable上调用sorted() But you now have the choice rather than have the list object forced on you. 但是你现在可以选择而不是强制列表对象。

And for most use cases in Python, you never really needed to have a whole list to begin with. 对于Python中的大多数用例,您从未真正需要一个完整的列表。 You usually iterate over such results. 您通常会迭代这些结果。 Sorting them is not the most common use case, indexing them isn't either. 对它们进行排序不是最常见的用例,索引它们也不是。 So for most use cases, the change is a win, giving programmers the tools to produce more efficient code with just the standard functions and types. 因此,对于大多数用例而言,更改是一种胜利,为程序员提供了仅使用标准函数和类型生成更高效代码的工具。

If you want to sort them, the iterable needs to be turned into a list (which sorted will handle for you)... but how often are you going to sort an enumerate object, compared to how often you're going to just iterate over it? 如果你想对它们进行排序,那么迭代需要转换成一个列表( sorted将为你处理)...但是你要多久经常对一个enumerate对象进行排序,与你再次迭代的频率相比超过它? What about sorting the items of a dict, compared to just iterating over them? 那么对dict的items进行排序,与仅仅迭代它们相比呢?

If your API produces a lazy iterator or other lazy iterable, you can turn that into a list with roughly the same amount of effort it would have taken to skip the iterator and produce a list directly. 如果您的API生成了一个惰性迭代器或其他惰性迭代器,您可以将其转换为一个列表,与跳过迭代器并直接生成列表所花费的工作量大致相同。 On the other hand, if your API produces a list, there's no way to avoid holding all the items in memory at once. 另一方面,如果您的API生成一个列表,则无法避免一次性将所有项目保留在内存中。 The iterator is more flexible. 迭代器更灵活。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM