我的理解yield from
是,它类似于yield
从可迭代对象中获取每个项目。然而,我在以下示例中观察到不同的行为。
我有Class1
class Class1:
def __init__(self, gen):
self.gen = gen
def __iter__(self):
for el in self.gen:
yield el
Run Code Online (Sandbox Code Playgroud)
和 Class2 的不同之处仅在于yield
将 for 循环替换为yield from
class Class2:
def __init__(self, gen):
self.gen = gen
def __iter__(self):
yield from self.gen
Run Code Online (Sandbox Code Playgroud)
下面的代码从给定类的实例中读取第一个元素,然后在 for 循环中读取其余元素:
a = Class1((i for i in range(3)))
print(next(iter(a)))
for el in iter(a):
print(el)
Run Code Online (Sandbox Code Playgroud)
Class1
这会为和产生不同的输出Class2
。对于Class1
输出是
0
1
2
Run Code Online (Sandbox Code Playgroud)
Class2
输出为
0
Run Code Online (Sandbox Code Playgroud)
yield from
产生不同行为的背后机制是什么?
在包装(内部)迭代器时,通常必须将__iter__
方法重新路由到底层的iterable.请考虑以下示例:
class FancyNewClass(collections.Iterable):
def __init__(self):
self._internal_iterable = [1,2,3,4,5]
# ...
# variant A
def __iter__(self):
return iter(self._internal_iterable)
# variant B
def __iter__(self):
yield from self._internal_iterable
Run Code Online (Sandbox Code Playgroud)
变体A和B之间是否有任何显着差异?Variant A返回iter()
已从内部iterable中查询过的迭代器对象.变量B返回一个生成器对象,该对象返回内部可迭代的值.出于某种原因,是其中一种还是其他的?在collections.abc
该yield from
版本中使用.该return iter()
变种是,我已经使用到现在的格局.