Profitability Issues in Python | Using helper functions

Given a string with many words, I want to change the word order. If the input signal Thanks for all the fish

, the output should be fish the all for Thanks

.

I am trying to solve this with generators to avoid creating a new list. I came up with the following solution:

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='')

      

However, the output of this code is " "

(string with spaces).

On the other hand, if I direct the print

items instead of putting them in, it works:

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)

      

It works and has a way out fish the all for Thanks

. But I don't want to just print it, I want to have the correct generator.

Finally, I found that if you avoid calls to foo

, it also works:

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='')

      

The output of this parameter is fish the all for Thanks

. This version gives me what I want (the correct generator), but I repeat the code inside its function.

I am the edge of the stack exchange thread about what gives, but I may have got it wrong. I figured out that the generator will run until it finds the next yield statement (or the end of the function). This issue makes me think that this is not exactly how it works, but other than that, I don't know.

How can I solve this with helper functions like in the first code snippet?

+3


source to share


1 answer


You can use yield from foo(...)

(see also PEP-380 under "Syntax for Delegating to a Subgenerator" ) or for whatever in foo(...): yield whatever

sequentially the yield

elements from the generator:

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

      



But as @trentcl pointed out in the comments, in your case you don't need the foo

-helper function because it basically does what it does islice

. Therefore, you can simply replace foo

with 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

      

+2


source







All Articles