Python 中的产量问题 |使用辅助函数
Problems with yield in Python | Using helper functions
给定一个包含很多单词的字符串,我想颠倒单词的顺序。如果输入是 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
元素而不是 yield 它们,它会起作用:
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 的作用,我在堆栈交换线程上写了红色,但我可能理解错了。
我的理解是,生成器将 运行 直到找到下一个 yield 语句(或函数结束)。
这个问题让我觉得这不是它的工作原理,但除此之外我一无所知。
如何使用第一个代码片段中的辅助函数来解决这个问题?
您可以使用 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
-helper 函数,因为它基本上也执行 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
给定一个包含很多单词的字符串,我想颠倒单词的顺序。如果输入是 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
元素而不是 yield 它们,它会起作用:
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 的作用,我在堆栈交换线程上写了红色,但我可能理解错了。 我的理解是,生成器将 运行 直到找到下一个 yield 语句(或函数结束)。 这个问题让我觉得这不是它的工作原理,但除此之外我一无所知。
如何使用第一个代码片段中的辅助函数来解决这个问题?
您可以使用 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
-helper 函数,因为它基本上也执行 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