采用迭代器而不是迭代的方法 [英] Methods that take iterators instead of iterables

查看:135
本文介绍了采用迭代器而不是迭代的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于迭代器和迭代(我的观察结果,如果我错了请纠正我):




  • 大多数构造函数(数组类型) )将迭代器作为质量构造函数

  • 明确地生成迭代器;或者在x中使用 x ....

  • 许多方法(主要是 itertools )返回迭代器(因为它们的作业要迭代?)

  • 采用迭代的方法会占用迭代器。 在所有情况下都是如此吗?

  • 采用迭代器的方法不会采用迭代(反之则不行)

  • 明确采用迭代器的唯一方法似乎是 next(..



<问题:




  • 还有其他方法需要迭代器吗?


  • 使用语法制作迭代器的其他方法是什么?例如: x in x for ...


  • 为什么python创建者离开 next(.. 是唯一采用迭代器的方法?他们可以很容易地将它变成一个带有额外参数的迭代方法(条件)?



解决方案

迭代器和迭代的语言有点主要的混淆来自术语可迭代,它可能是也可能不是迭代器的超集,取决于它的使用方式。



这是怎么回事我会对事情进行分类:



iterable 是可以迭代的任何对象。也就是说,它有一个返回迭代器的 __ iter __()方法,或者它可以用整数索引(引发 IndexError 当它们超出范围时的异常),这允许Python自动为它构建迭代器。这是一个非常广泛的类别。



迭代器是一个遵循迭代器协议的对象。它有一个 __ next __()方法(在Python 2中拼写为 next )产生下一个项目,或者引发 StopIteration 例外,如果没有更多值可用。迭代器也必须有一个返回自身的 __ iter __()方法,因此所有迭代器也是可迭代的(因为它们符合上面给出的iterable的定义)。



非迭代器可迭代不是迭代器的任何可迭代。这通常是人们使用术语可迭代而不是迭代器时的意思。在许多上下文中,一个更好的术语可能是序列,但这更具体(一些非序列对象是非迭代器迭代,就像允许迭代其键的字典)。这类对象的重要特性是你可以多次迭代它们,迭代器可以相互独立工作。



所以试着回答你的具体问题:



任何函数都很少有理由要求特定的迭代器。通常可以通过在参数上调用 iter()来获取迭代器,或者使用<$,通常可以使函数与任何类型的可迭代参数一起工作。 c $ c> for 循环,它在幕后创建迭代器。



反之亦然。如果函数需要非迭代器可迭代,则可能需要多次迭代该参数,因此迭代器将无法正常工作。 Python标准库(和内置函数)中的函数很少有这样的限制。如果他们需要在可迭代参数上多次迭代,如果它不是序列,它们通常会在开始时将其转储到序列类型(例如列表)中。



许多函数返回迭代器。例如,所有生成器对象都是迭代器(由生成器函数返回的那些和使用生成器表达式创建的那些)。文件对象也是迭代器(虽然它们稍微违反了迭代器协议,因为你可以在使用 seek()方法耗尽它们之后重新启动它们。并且 itertools 模块中的所有函数和类型都返回迭代器,但是一些内置函数也是如此,例如 map()(in Python 3)。



next()函数确实不常见,因为特别需要迭代器。这是因为它被定义为迭代协议本身的一部分。它完全等同于在迭代器上调用 __ next __()方法,只是更好读。它还有一个双参数形式,它抑制了 StopIteration 异常,否则如果迭代器耗尽则会引发异常(它返回默认参数)。


Regarding iterators and iterables (my observation only and please correct me if I am wrong):

  • Most constructors (of arrayish-types) take iterators as mass-constructor
  • iterators are explicitly made; or by using x in x for....
  • Many methods (mostly, itertools) returns iterators (because their jobs is to iterate?)
  • Methods that take iterables take iterators. Is this true in all cases?
  • Methods that take iterators won't take iterables (reverse is not true)
  • The only method that explicitly takes an iterator seems to be next(..

Questions:

  • Are there other methods that take iterators?

  • What are the other ways to make iterators with syntax? eg: x in x for...

  • Why did the python creators leave next(.. to be the only method taking iterators? They could easily make it into a method taking iterable with extra arguments(conditions)?

解决方案

The language around iterators and iterables is a bit confusing. The main confusion comes from the term "iterable", which may or may not be a superset of "iterator", depending on how it's being used.

Here's how I'd categorize things:

An iterable is any object that can be iterated upon. That is, it has an __iter__() method that returns an iterator, or it is indexable with integers (raising an IndexError exception when they're out of range), which lets Python build an iterator for it automatically. This is a very broad category.

An iterator is an object that follows the iterator protocol. It has a __next__() method (spelled next in Python 2) that yields the next item, or raises StopIteration exception if there are no more values available. An iterator also must have an __iter__() method that returns itself, so all iterators are also iterable (since they meet the definition of "iterable" given above).

A non-iterator iterable is any iterable that is not an iterator. This is often what people mean when they use the term "iterable" in contrast to "iterator". A better term in many contexts might be "sequence", but that's a bit more specific (some non-sequence objects are non-iterator iterables, like dictionaries which allow iteration over their keys). The important feature of this category of objects is that you can iterate on them multiple times, and the iterators work independently of one another.

So to try to answer your specific questions:

There's rarely a good reason for any function to require an iterator specifically. Functions can usually be made to work just as well with any kind of iterable argument, either by calling iter() on the argument to get an iterator, or by use a for loop which creates the iterator behind the scenes.

The reverse is different. If a function requires a non-iterator iterable, it may need to iterate on the argument several times and so an iterator will not work properly. Functions in the Python standard library (and builtins) rarely have such a limitation though. If they need to iterate multiple times on an iterable argument, they'll often dump it into a sequence type (e.g. a list) at the start if it's not a sequence already.

Many functions return iterators. All generator objects are iterators, for instance (both those returned by generator functions and those created with generator expressions). File objects are also iterators (though they violate the iterator protocol a little bit since you can restart them after they're exhausted using their seek() method). And all the functions and types in the itertools module return iterators, but so do some builtins like map() (in Python 3).

The next() function is indeed unusual since specifically requires an iterator. This is because it's defined as a part of the iteration protocol itself. It's exactly equivalent to calling the __next__() method on the iterator, just nicer to read. It also has a two-argument form which suppresses the StopIteration exception that would otherwise be raised if the iterator is exhausted (it returns the default argument instead).

这篇关于采用迭代器而不是迭代的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆