如何解决取消注释 `if False: yield` 改变了 `__iter__` 行为
当我取消注释 __iter__
时,我不明白为什么 if False: yield
的行为会发生变化。条件永远不为真,那么为什么结果会改变?
class Example:
def __init__(self):
self.lst = [1,2,3]
self.size = 3
def __iter__(self):
self.n = 0
#if False: yield
return self
def __next__(self):
self.n += 1
if self.n > self.size:
raise stopiteration
return self.lst[self.n-1]
ex = Example()
for i in ex:
print(i)
如果我取消对 if False: yield
方法中的 __iter__
的注释,则迭代器将停止工作并且不会打印任何内容,即使该行从未被执行。
解决方法
当您取消注释行 if False: yield
时,Python 解释器会将 def __iter__(self)
编译为 generator
而不是函数。生成器是封装在函数中的迭代器,只要 next
语句继续提供值,它就会一直返回值(在 yield
调用上),并且在生成器返回时会引发 StopIteration
其功能:
>>> class A:
... def __iter__(self):
... if False:
... yield
...
>>> a = A()
>>> type(iter(a))
<class 'generator'>
>>> class B:
... def __iter__(self):
... return self
... def __next__(self):
... return 1
...
>>> type(iter(B()))
<class '__main__.B'>
当您注释该行时,您的 __iter__
是一个常规函数并返回 self
作为迭代器,任何实现 __next__
方法的类都可以用作迭代器;如果你没有你会得到这个错误:
>>> class B:
... def __iter__(self):
... return self
...
>>> type(iter(B()))
Traceback (most recent call last):
File "<stdin>",line 1,in <module>
TypeError: iter() returned non-iterator of type 'B'
请注意,如果 __iter__
所做的只是返回 self
而您甚至不需要实现它,那么只需 __next__
就足够了。您的 __iter__
实现甚至是危险的:多个 iter(ex)
调用都将返回与迭代器相同的 ex
对象,并将重置所有这些“迭代器”的 n
实际上使用相同的ex
:
>>> ex = Example()
>>> itr1 = iter(ex)
>>> print(next(itr1),next(itr1))
1 2
>>> iter(ex)
>>> print(next(itr1))
1
再次调用 iter
会重置您之前的迭代器引用吗?我无法想象这就是您想要实现的目标 ;)
如果条件为 if
,则 False
循环永远不会执行。因此,当您使用 if False:
时,因为条件是 False
,它永远不会执行。此外,您没有在 yield
中指定任何内容。
这可以改写为,
class Example:
def __init__(self):
self.lst = [1,2,3]
self.size = 3
self.n = 0
def __iter__(self):
self.n = 0
for i in self.lst:
yield i
def __next__(self):
self.n += 1
if self.n > self.size:
raise StopIteration
return self.lst[self.n-1]
ex = Example()
for i in ex:
print(i)
输出将如您所愿。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。