Python 只有作为generator func实现的_uiter__;要使用next()
我有一个Python 只有作为generator func实现的_uiter__;要使用next(),python,python-3.x,iterator,Python,Python 3.x,Iterator,我有一个\uuuu iter\uuuu类,定义如下: class MyIterator: def __iter__(self): for value in self._iterator: if is_iterator(value): yield from value else: yield value 我想做next(我的迭代器),但我必须实现\uuuuuu
\uuuu iter\uuuu
类,定义如下:
class MyIterator:
def __iter__(self):
for value in self._iterator:
if is_iterator(value):
yield from value
else:
yield value
我想做next(我的迭代器)
,但我必须实现\uuuuuuuuuuuuuuuuuu
。但是它会把这个简单的实现变成一个相当复杂的实现——或者实际上我不知道如何实现它,而不是将\uuu iter\uuu
定义为一个生成器函数
一般来说,如果将\uuuuu iter\uuuuu
实现为一个生成器功能,如果没有生成器可能很难实现,那么如果我想使用\uuuuu next\uuu
注:显然,
next(iter(我的迭代器))
有效,但我不想这样做。正如@BrenBarm评论的那样,显然的答案是通过保持self来返回next(iter(self))
,或者next(self.\iter\u self)
。正如@BrenBarm评论的那样,显然的答案是返回next(iter(self))
,或者next(self.\u iter\u self)
,保持self.\u iter\u self=iter(self)
。我不能就这么想。
- 迭代器是一个具有
\uuuuuuuuuuuuuuuuuuuuuuuu
方法的对象,该方法返回值,直到最后引发StopIteration
- iterable是具有返回迭代器的
\uuuuu iter\uuuu
方法的对象
- 生成器是python在函数或方法包含yield语句时创建的一个特殊的iterable
在您的示例中,\uuuuuuuuuuuuuuu iter\uuuuuuuu
具有收益率,因此它是一个生成器。这意味着它返回另一个iterable,而不是迭代器。这就是为什么你必须下一步(iter(my_iterator))
去做一件奇怪的事情,但这不起作用,因为它每次都会重新启动枚举
如何最好地解决这个问题取决于您如何使用这个类。您可以创建一个生成器函数,然后根据需要使用iter
生成迭代器:
import collections.abc
def is_iterator(i):
return isinstance(i, collections.abc.Iterable)
def MyIterator(iterable):
for value in iterable:
if is_iterator(value):
yield from value
else:
yield value
test_this = [1,2, [3, 4, 5], [6], [], 7, 'foo']
my_iterator = iter(MyIterator(test_this))
try:
while True:
print(next(my_iterator))
except StopIteration:
pass
或者,您可以实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是您不能使用yield
,并且必须在每次调用时返回一个值,直到外部迭代器完成并引发StopIteration
import collections.abc
class MyIterator:
def __init__(self, iterable):
self._iterator = iter(iterable)
self._iterating = None
def __next__(self):
while True:
if self._iterating is not None:
try:
return next(self._iterating)
except StopIteration:
self._iterating = None
value = next(self._iterator)
if isinstance(value, collections.abc.Iterable):
self._iterating = iter(value)
else:
return value
test_this = [1,2, [3, 4, 5], [6], [], 7, 'foo']
my_iterator = MyIterator(test_this)
try:
while True:
print(next(my_iterator))
except StopIteration:
pass
- 迭代器是一个具有
\uuuuuuuuuuuuuuuuuuuuuuuu
方法的对象,该方法返回值,直到最后引发StopIteration
- iterable是具有返回迭代器的
\uuuuu iter\uuuu
方法的对象
- 生成器是python在函数或方法包含yield语句时创建的一个特殊的iterable
在您的示例中,\uuuuuuuuuuuuuuu iter\uuuuuuuu
具有收益率,因此它是一个生成器。这意味着它返回另一个iterable,而不是迭代器。这就是为什么你必须下一步(iter(my_iterator))
去做一件奇怪的事情,但这不起作用,因为它每次都会重新启动枚举
如何最好地解决这个问题取决于您如何使用这个类。您可以创建一个生成器函数,然后根据需要使用iter
生成迭代器:
import collections.abc
def is_iterator(i):
return isinstance(i, collections.abc.Iterable)
def MyIterator(iterable):
for value in iterable:
if is_iterator(value):
yield from value
else:
yield value
test_this = [1,2, [3, 4, 5], [6], [], 7, 'foo']
my_iterator = iter(MyIterator(test_this))
try:
while True:
print(next(my_iterator))
except StopIteration:
pass
或者,您可以实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是您不能使用yield
,并且必须在每次调用时返回一个值,直到外部迭代器完成并引发StopIteration
import collections.abc
class MyIterator:
def __init__(self, iterable):
self._iterator = iter(iterable)
self._iterating = None
def __next__(self):
while True:
if self._iterating is not None:
try:
return next(self._iterating)
except StopIteration:
self._iterating = None
value = next(self._iterator)
if isinstance(value, collections.abc.Iterable):
self._iterating = iter(value)
else:
return value
test_this = [1,2, [3, 4, 5], [6], [], 7, 'foo']
my_iterator = MyIterator(test_this)
try:
while True:
print(next(my_iterator))
except StopIteration:
pass
如果您的类应该是迭代器,那么它不应该将其\uuuuu iter\uuuu
方法实现为生成器函数。这使得类是可重用的,但不是迭代器。迭代器的\u iter\u
方法应该返回自身
如果您确实希望类成为迭代器,请尝试以下操作:
class MyIterator:
def __init__(self, iterator):
self._iterator = iterator
self._subiterator = None
def __iter__(self):
return self
def __next__(self):
while True:
if self._subiterator is None:
value = next(self._iterator) # may raise StopIteration
try: # could test is_iterator(value) here for LBYL style code
self._subiterator = iter(value)
except TypeError:
return value
try:
return next(self._subiterator)
except StopIteraton:
self._subiterator = None
next(self.\u迭代器)
调用可能会引发StopIteration
,我故意没有捕捉到它。这个异常是我们已经完成迭代的信号,所以如果我们捕捉到它,我们只需要再次引发它
这段代码使用了一种“请求原谅比请求许可更容易”(EAFP)的方法来检测给定迭代器中的iterable项。它只需在每一个上调用iter
,并捕获TypeError
,如果它们不可编辑,则会引发该错误。如果您更愿意坚持“三思而后行”(LBYL)风格,并使用is_iterator
显式测试(名称不好,因为它检查的是任何类型的iterable,而不仅仅是iterator),您可以将内部try
替换为:
if is_iterator(value):
return value
else:
self._subiterator = iter(value)
在Python代码中,我通常更喜欢EAFP样式而不是LBYL样式,但在某些情况下,两者都可以做得更好。其他时候,这只是风格的问题。如果你的类应该是一个迭代器,那么它不应该把它的\uuuu iter\uuu
方法实现为生成器函数。这使得类是可重用的,但不是迭代器。迭代器的\u iter\u
方法应该返回自身
如果您确实希望类成为迭代器,请尝试以下操作:
class MyIterator:
def __init__(self, iterator):
self._iterator = iterator
self._subiterator = None
def __iter__(self):
return self
def __next__(self):
while True:
if self._subiterator is None:
value = next(self._iterator) # may raise StopIteration
try: # could test is_iterator(value) here for LBYL style code
self._subiterator = iter(value)
except TypeError:
return value
try:
return next(self._subiterator)
except StopIteraton:
self._subiterator = None
next(self.\u迭代器)
调用可能会引发StopIteration
,我故意没有捕捉到它。这个异常是我们已经完成迭代的信号,所以如果我们捕捉到它,我们只需要再次引发它
这段代码使用了一种“请求原谅比请求许可更容易”(EAFP)的方法来检测给定迭代器中的iterable项。它只需在每一个上调用iter
,并捕获TypeError
,如果它们不可编辑,则会引发该错误。如果您更愿意坚持“三思而后行”(LBYL)风格,并使用is_iterator
显式测试(名称不好,因为它检查的是任何类型的iterable,而不仅仅是iterator),您可以将内部try
替换为:
if is_iterator(value):
return value
else:
self._subiterator = iter(value)
在Python代码中,我通常更喜欢EAFP样式而不是LBYL样式,但在某些情况下,两者都可以做得更好。其他时候,这只是风格的问题。您需要更多地解释您打算如何进行迭代。你可以在下一步写一个