【问题标题】:Problems with yield in Python | Using helper functionsPython中的yield问题|使用辅助函数
【发布时间】:2017-05-04 14:01:21
【问题描述】:

给定一个包含很多单词的字符串,我想颠倒单词的顺序。如果输入为Thanks for all the fish,则输出应为fish the all for Thanks

我正在尝试使用 generators 解决此问题,以避免创建新列表。 我想出了以下解决方案:

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 的作用,但我可能理解错了。 我的理解是生成器将一直运行,直到找到下一个 yield 语句(或函数结束)。 这个问题让我觉得这不是它的工作原理,但除此之外我一无所知。

如何使用第一个代码 sn-p 中的帮助函数来解决这个问题?

【问题讨论】:

    标签: python python-3.x generator yield


    【解决方案1】:

    您可以使用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 在 cmets 中指出的那样,在您的情况下,您不需要 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
    

    【讨论】:

    • 事实上,foo 是一个空操作;你可以yield from islice(s, i+1, j)
    • 感谢你们俩。 @trentcl foono-op 是什么意思?
    • @FranciscoFigari 您不需要foo 函数。根据评论,我添加了第二个示例,其中我直接使用了islice 而没有foo
    • @Mseifert 我的意思是“无操作”是什么意思。它的意思是“不必要的代码”?
    • @FranciscoFigari “无操作”或NOP 是什么都不做的东西(命令、代码行、指令等)。我使用的术语很宽松,因为严格来说,foo 做了一些事情:它调用了islice。它只是不会为直接调用islice 增加任何价值
    猜你喜欢
    • 1970-01-01
    • 2021-05-24
    • 2015-03-26
    • 2021-08-22
    • 1970-01-01
    • 2012-12-20
    • 2022-01-08
    • 2019-01-17
    • 1970-01-01
    相关资源
    最近更新 更多