在Python中,可迭代对象的接口是迭代器接口的子集。这有一个好处,在许多情况下,它们可以以相同的方式处理。然而,两者之间有一个重要的语义差别,因为对于可迭代对象,
例如,当想要循环多次时,区别就很重要。如果给定一个迭代器,则第二个循环将无法工作,因为迭代器已经被使用完并直接引发
检测
有没有更符合Python风格的方式来进行这样的测试?我知道这听起来像LBYL与EAFP的经典案例,所以也许我应该放弃?还是我漏掉了什么?
编辑:S.Lott在下面的回答中说,这主要是想要在迭代器上进行多次通行的问题,而且一开始就不应该这样做。然而,在我的情况下,数据非常大,并且根据情况必须多次传递以进行数据处理(绝对没有其他方法)。
可迭代对象也是由用户提供的,对于只需要一次遍历的情况,它可以使用迭代器(例如为了简单起见创建的生成器)。但是,如果需要多次遍历时,最好防止用户仅提供迭代器的情况。
编辑2: 实际上,这是一个非常好的抽象基类示例。迭代器和可迭代对象中的__iter__方法具有相同的名称,但语义上不同!因此,hasattr是无用的,但isinstance提供了一个干净的解决方案。
__iter__
返回一个新的迭代器对象,而不仅仅是self
。如何测试一个可迭代对象确实是一个可迭代对象而不是迭代器?从概念上讲,我理解可迭代对象是集合,而迭代器只管理迭代(即跟踪位置),但本身不是集合。例如,当想要循环多次时,区别就很重要。如果给定一个迭代器,则第二个循环将无法工作,因为迭代器已经被使用完并直接引发
StopIteration
。检测
next
方法似乎很危险且不正确。应该只检查第二个循环是否为空吗?有没有更符合Python风格的方式来进行这样的测试?我知道这听起来像LBYL与EAFP的经典案例,所以也许我应该放弃?还是我漏掉了什么?
编辑:S.Lott在下面的回答中说,这主要是想要在迭代器上进行多次通行的问题,而且一开始就不应该这样做。然而,在我的情况下,数据非常大,并且根据情况必须多次传递以进行数据处理(绝对没有其他方法)。
可迭代对象也是由用户提供的,对于只需要一次遍历的情况,它可以使用迭代器(例如为了简单起见创建的生成器)。但是,如果需要多次遍历时,最好防止用户仅提供迭代器的情况。
编辑2: 实际上,这是一个非常好的抽象基类示例。迭代器和可迭代对象中的__iter__方法具有相同的名称,但语义上不同!因此,hasattr是无用的,但isinstance提供了一个干净的解决方案。
iter(obj) is obj
,在我看来是正确的,但这并不是保证。 - tzotnext()
方法,其行为如上所述,以及一个返回 self 的__iter__()
方法。 - Piotr Dobrogost