如何检查迭代器是否实际上是迭代器容器?
How do I check if an iterator is actually an iterator container?
我在下面有一个迭代器容器的虚拟示例(真正的示例读取一个太大而无法放入内存的文件):
class DummyIterator:
def __init__(self, max_value):
self.max_value = max_value
def __iter__(self):
for i in range(self.max_value):
yield i
def regular_dummy_iterator(max_value):
for i in range(max_value):
yield i
这让我可以多次迭代值 ,这样我就可以实现这样的东西:
def normalise(data):
total = sum(i for i in data)
for val in data:
yield val / total
# this works when I call next()
normalise(DummyIterator(100))
# this doesn't work when I call next()
normalise(regular_dummy_iterator(100))
我如何检查正在传递给迭代器容器而不是普通生成器的规范化函数?
首先:没有迭代器容器这样的东西。你有一个 iterable.
一个可迭代对象产生一个迭代器。任何迭代器也是可迭代的,但会生成 自身 作为迭代器:
>>> list_iter = iter([])
>>> iter(list_iter) is list_iter
True
如果 iter(ob) is ob
测试为假,则您没有迭代器。
你可以测试你是否有一个迭代器(消耗一次 next
引发 StopIteration
异常)vs 只是 一个可迭代的(可能被迭代多次)通过使用 collections.abc
module。这是一个例子:
from collections.abc import Iterable, Iterator
def my_iterator():
yield 1
i = my_iterator()
a = []
isinstance(i, Iterator) # True
isinstance(a, Iterator) # False
使 my_iterator()
成为 Iterator
的是 __next__
和 __iter__
魔术方法的存在(顺便说一句,基本上是幕后发生的事情当您在 collections.abc
抽象基础上调用 isinstance
时,class 是对某些魔术方法是否存在的测试)。
请注意,迭代器 也是一个 Iterable
,空列表也是如此(即,两者都有 __iter__
魔术方法):
isinstance(i, Iterable) # True
isinstance(a, Iterable) # True
另请注意,,当您将通用 iter()
函数应用于两者时,您会得到一个迭代器:
isinstance(iter(my_iterator()), Iterator) # True
isinstance(iter([])), Iterator) # True
这里[]
和my_iterator()
的区别是iter(my_iterator())
returns本身作为迭代器,而iter([])
每次都会产生一个 新的迭代器 。
正如 MP 的相同回答中已经提到的,您上面的对象不是 "iterator container." 它是一个可迭代对象,即 "an iterable"。它是否 "contains" 没有真正相关的东西;包含的概念由抽象基 class Container
表示。 Container
可能是可迭代的,但不一定是。
我在下面有一个迭代器容器的虚拟示例(真正的示例读取一个太大而无法放入内存的文件):
class DummyIterator:
def __init__(self, max_value):
self.max_value = max_value
def __iter__(self):
for i in range(self.max_value):
yield i
def regular_dummy_iterator(max_value):
for i in range(max_value):
yield i
这让我可以多次迭代值 ,这样我就可以实现这样的东西:
def normalise(data):
total = sum(i for i in data)
for val in data:
yield val / total
# this works when I call next()
normalise(DummyIterator(100))
# this doesn't work when I call next()
normalise(regular_dummy_iterator(100))
我如何检查正在传递给迭代器容器而不是普通生成器的规范化函数?
首先:没有迭代器容器这样的东西。你有一个 iterable.
一个可迭代对象产生一个迭代器。任何迭代器也是可迭代的,但会生成 自身 作为迭代器:
>>> list_iter = iter([])
>>> iter(list_iter) is list_iter
True
如果 iter(ob) is ob
测试为假,则您没有迭代器。
你可以测试你是否有一个迭代器(消耗一次 next
引发 StopIteration
异常)vs 只是 一个可迭代的(可能被迭代多次)通过使用 collections.abc
module。这是一个例子:
from collections.abc import Iterable, Iterator
def my_iterator():
yield 1
i = my_iterator()
a = []
isinstance(i, Iterator) # True
isinstance(a, Iterator) # False
使 my_iterator()
成为 Iterator
的是 __next__
和 __iter__
魔术方法的存在(顺便说一句,基本上是幕后发生的事情当您在 collections.abc
抽象基础上调用 isinstance
时,class 是对某些魔术方法是否存在的测试)。
请注意,迭代器 也是一个 Iterable
,空列表也是如此(即,两者都有 __iter__
魔术方法):
isinstance(i, Iterable) # True
isinstance(a, Iterable) # True
另请注意,iter()
函数应用于两者时,您会得到一个迭代器:
isinstance(iter(my_iterator()), Iterator) # True
isinstance(iter([])), Iterator) # True
这里[]
和my_iterator()
的区别是iter(my_iterator())
returns本身作为迭代器,而iter([])
每次都会产生一个 新的迭代器 。
正如 MP 的相同回答中已经提到的,您上面的对象不是 "iterator container." 它是一个可迭代对象,即 "an iterable"。它是否 "contains" 没有真正相关的东西;包含的概念由抽象基 class Container
表示。 Container
可能是可迭代的,但不一定是。