Python 为什么从内部生成的下一个对象返回生成器对象?
我正在使用Python 为什么从内部生成的下一个对象返回生成器对象?,python,generator,next,Python,Generator,Next,我正在使用yield在类中的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()函数中返回下一个值。但是,它不会返回下一个值,而是返回生成器对象 我正在努力更好地理解迭代器和yield。我可能做得不对 看一看 class MyString: def __init__(self,s): self.s=s def __iter__(self): return self def
yield
在类中的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()函数中返回下一个值。但是,它不会返回下一个值,而是返回生成器对象
我正在努力更好地理解迭代器和yield
。我可能做得不对
看一看
class MyString:
def __init__(self,s):
self.s=s
def __iter__(self):
return self
def __next__(self):
for i in range(len(self.s)):
yield(self.s[i])
r=MyString("abc")
i=iter(r)
print(next(i))
这将返回:
在这种情况下,0x032C05A0处的生成器对象\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在对象上调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,将启动生成器并返回它(此时不执行任何魔术)
在这种情况下,您可能完全不需要定义\uuuuuuuuuuuuuuuuuuuuuuuuuu
:
class MyString:
def __init__(self,s):
self.s=s
def __iter__(self):
for i in range(len(self.s)):
yield(self.s[i])
# Or...
# for item in self.s:
# yield item
如果您想使用\uuuu iter\uuuuu
和\uuuuu next\uuuuuuu
(定义一个而不是简单地制作一个),您可能需要执行以下操作:
class MyString:
def __init__(self,s):
self.s = s
self._ix = None
def __iter__(self):
return self
def __next__(self):
if self._ix is None:
self._ix = 0
try:
item = self.s[self._ix]
except IndexError:
# Possibly reset `self._ix`?
raise StopIteration
self._ix += 1
return item
让我们看看\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。发件人:
迭代器。下一个
从容器中返回下一个项目。如果没有其他项,则引发StopIteration异常
现在让我们看看yield
语句的作用。另一段摘录自:
在函数体中使用屈服表达式会导致该函数
做发电机
及
调用生成器函数时,它返回一个称为
发电机
现在比较\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是包含yield
关键字的函数返回迭代器。因此,在\uuuuuuuuuuuuuu
方法中使用yield
,将生成生成迭代器的迭代器
如果您想使用yield
使您的类更易理解,请使用以下方法:
\uu iter\uu
方法应该返回一个迭代器,而yield
关键字正好让它返回迭代器
为了完整起见,下面是如何使用\uuuuuuuuuuuuuuuuuuuu
方法实现迭代器。您必须跟踪迭代的状态,并返回相应的值。最简单的解决方案可能是每次调用\uuu next\uuu
时增加索引:
class MyString:
def __init__(self,s):
self.s = s
self.index = -1
def __iter__(self):
return self
def __next__(self):
self.index += 1
if self.index >= len(self.s):
raise StopIteration
return self.s[self.index]
据我所知,生成器函数只是带有next函数的类的语法糖。例如:
>>> def f():
i = 0
while True:
i += 1
yield i
>>> x = f()
>>> x
<generator object f at 0x0000000000659938>
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> class g(object):
def __init__(self):
self.i = 0
def __next__(self):
self.i += 1
return self.i
>>> y = g()
>>> y
<__main__.g object at 0x000000000345D908>
>>> next(y)
1
>>> next(y)
2
>>> next(y)
3
这可能是实现我认为您正在寻找的目标的最简单的方法。因此,将\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>作为生成器并不真正有意义,或者这意味着MyString
迭代器的每个值都是生成器。MyString不应该定义\uu<代码>\uuuuuuuuuuuuuuuuuu下一步\uuuuuuuuu
用于迭代器,而不是iterables。类似地,它不应该为\uuuu iter\uuuu
返回self
。我没有看到最近的编辑。我在问为什么会这样missing@MosesKoledoye--是的,这是我在你发表评论时纠正的原始帖子中的一个疏忽。我还意识到调用iter(mystring)
可能不应该重置迭代。。。谢谢你看着我的背。:-)您是否不需要在def\uuuu iter\uuuu(self)
上执行self.index=-1
来重置迭代,然后,当稍后调用或嵌套为以用于in列表时。。。对于列表中的b。。。如果一个=b、 ..
@user嗯,作为自身迭代器的对象通常不会在\uu iter\uu
方法中重置。例如,考虑一个文件对象。您只能在上面迭代一次。
>>> def f():
i = 0
while True:
i += 1
yield i
>>> x = f()
>>> x
<generator object f at 0x0000000000659938>
>>> next(x)
1
>>> next(x)
2
>>> next(x)
3
>>> class g(object):
def __init__(self):
self.i = 0
def __next__(self):
self.i += 1
return self.i
>>> y = g()
>>> y
<__main__.g object at 0x000000000345D908>
>>> next(y)
1
>>> next(y)
2
>>> next(y)
3
class MyString:
def __init__(self,s):
self.s=s
self._i = -1
def __iter__(self):
return self
def __next__(self):
self._i += 1
if self._i >= len(self.s):
raise StopIteration
return self.s[self._i]