给定一个包含许多单词的字符串,我想颠倒单词的顺序。如果输入为Thanks for all the fish
,则输出应为fish the all for Thanks
。
我尝试使用生成器解决此问题,以避免创建新列表。 我提出了以下解决方案:
from itertools import islice
def foo(s, begin, end):
for elem in islice(s, begin, end):
yield elem
def baz(s):
i = len(s)
j = len(s)
while True:
i -= 1
if i == -1:
foo(s, i+1, j)
break
if s[i] == ' ':
foo(s, i+1, j)
yield ' '
j = i
s = "Thanks for all the fish"
g = baz(s)
for x in g: print(x, end='')
但是,此代码的输出为" "
(仅包含空格的字符串)。
另一方面,如果我直接print
元素而不是产生它们,它就可以了:
from itertools import islice
def foo(s, begin, end):
for elem in islice(s, begin, end):
print(elem, end='')
def baz(s):
i = len(s)
j = len(s)
while True:
i -= 1
if i == -1:
foo(s, i+1, j)
break
if s[i] == ' ':
foo(s, i+1, j)
print(' ', end='')
j = i
s = "Thanks for all the fish"
g = baz(s)
这可以作为输出fish the all for Thanks
。但我不想只是打印它,我想要一个正确的发电机。
最后,我发现如果避免调用foo
,它也会起作用:
from itertools import islice
def baz(s):
i = len(s)
j = len(s)
while True:
i -= 1
if i == -1:
for elem in islice(s, i+1, j):
yield elem
break
if s[i] == ' ':
for elem in islice(s, i+1, j):
yield elem
yield ' '
j = i
s = "Thanks for all the fish"
g = baz(s)
for x in g: print(x, end='')
此输出为fish the all for Thanks
。
这个版本给了我想要的东西(一个正确的生成器),但我在其函数内重复代码。
我重新讨论了关于收益率的堆栈交换线程,但我可能已经理解错了。 我所理解的是,生成器将一直运行,直到找到下一个yield语句(或函数结束)。 这个问题让我觉得这不是它的确切运作方式,但除此之外,我一无所知。
如何使用第一个代码段中的辅助函数解决此问题?
答案 0 :(得分:2)
您可以使用yield from foo(...)
(另请参阅PEP-380 on "Syntax for Delegating to a Subgenerator")或for whatever in foo(...): yield whatever
来成功yield
来自生成器的元素:
def baz(s):
i = len(s)
j = len(s)
while True:
i -= 1
if i == -1:
yield from foo(s, i+1, j) # yield from syntax
break
if s[i] == ' ':
for item in foo(s, i+1, j): # for-loop over generator
yield item
yield ' '
j = i
但是,正如@trentcl在评论中指出的那样,在你的情况下你不需要foo
- 帮助函数,因为它基本上也是islice
所做的。因此,您只需将foo
替换为islice
:
def baz(s):
i = len(s)
j = len(s)
while True:
i -= 1
if i == -1:
yield from islice(s, i+1, j) # yield from syntax
break
if s[i] == ' ':
for item in islice(s, i+1, j): # for-loop over generator
yield item
yield ' '
j = i