Posts: 134
Threads: 54
Joined: Mar 2020
Oct-07-2025, 05:20 PM
(This post was last modified: Oct-07-2025, 05:30 PM by SpongeB0B.)
Hi
I would like to have a simple generator like
def alternate():
while True:
yield 'yes'
yield 'no'
#generator
YN = alternate()
sample = '!A!A'.replace('!A',next(YN))So I'm expecting yesno instead I got
Output: yesyes
I've tried also with re.sub(), but still the same outcome..
any ideas ?
Thanks.
Posts: 134
Threads: 54
Joined: Mar 2020
Nevermind ;)
I've found a solution. I'll post tomorrow. cheers
Posts: 232
Threads: 0
Joined: Jun 2019
Hi,
the replace methods for strings expects min two arguments: the string to replace and what it should be replaced with - as you correctly use. Your alternativefunction / generator returns exactly one string, alternating between yes and no. So next(YN) return either yes or no. Your program does exactly what you programmed - your expectation is wrong. You are expecting the generator to return twice a value with one call only - this won't work.
What are you really trying to achieve? I guess the hyper simplified example isn't the real world code you are running. In the given example, using a generator is pointless and the replacement doesn't really make sense. I guess it would help (you) a lot to deliver a bit more context.
Regards, noisefloor
Posts: 1,301
Threads: 151
Joined: Jul 2017
Oct-08-2025, 02:26 AM
(This post was last modified: Oct-08-2025, 02:26 AM by Pedroski55.)
Don't like the look of that while True without any exit condition! Better use range.
def alternate():
for i in range(5):
yield 'yes'
yield 'no'
#generator
YN = alternate()
for duh in YN:
print('!A!A'.replace('!A', duh)) Sorry, as usual I didn't read the question carefully. You want "yesno" as output, I believe.
def yes():
for i in range(5):
yield 'yes'
def no():
for j in range(5):
yield 'no'
#generator
ja = yes()
nein = no()
for k in range(5):
word = next(ja) + next(nein)
print('!A!A'.replace('!A!A', word))But that seems unnecessarily complicated.
out = ('yesno' for i in range(5))
for o in out:
print( '!A!A'.replace('!A', o))The above gives a double 'yesnoyesno' change replace('!A' for replace('!A!A' if you want just 'yesno'
Posts: 1,301
Threads: 151
Joined: Jul 2017
Or, to stick with your original idea:
def alternate():
for i in range(5):
yield 'yes'
yield 'no'
#generator
YN = alternate()
for duh in YN:
word = duh + next(YN)
print('!A!A'.replace('!A!A', word))
Posts: 6,981
Threads: 22
Joined: Feb 2020
The function argument is evaluated first. The result is passed to the function. Your code is identical in functionality to:
word = next(YN)
sample = '!A!A'.replace('!A', word)There is no way you can make replace() call next(YN) twice. You can pass a function (or generator) as an argument, and call the function multiple times, or have the function return multiple values, but that only works because everybody is in on the trick.
Posts: 8,204
Threads: 162
Joined: Sep 2016
Oct-08-2025, 06:10 AM
(This post was last modified: Oct-08-2025, 06:11 AM by buran.)
Although this smells like XY problem from miles away
in python 3.12+
from itertools import cycle, batched
replacement = batched(cycle(['yes', 'no']), 2)
print('A!A!'.replace('A!A!', ''.join(next(replacement))))Output: yesno
And another go
from itertools import cycle
replacement = cycle(['yes', 'no'])
foo, bar = 'A!A!A!', None
while foo != bar:
bar, foo = foo, foo.replace('A!', next(replacement), 1)
print(foo)
noisefloor likes this post
Posts: 6,981
Threads: 22
Joined: Feb 2020
I don't think this is an XY problem. I think it is a "How does X work" question. The answer is that passing a generator result as an argument passes the result, not the generator. calling next(YN) passed "yes" to replace(), not the generator YN.
cycle and batch do not solve the "problem", they are tools that let you write a solution around the problem. It's no different than writing this:
from itertools import cycle, batched
def alternate():
while True:
yield "yes"
yield "no"
def generator_replace(string, pattern, generator):
result = string
while pattern in result:
result = result.replace(pattern, next(generator), 1)
return result
print(generator_replace("A A", "A", alternate()))
print(generator_replace("B B B", "B", cycle(("yes", "no"))))
print(generator_replace("C C C C", "C", cycle(("yes", "no"))))Somewhere, somebody has to do a loop, and you have to write the loop.
Posts: 1,301
Threads: 151
Joined: Jul 2017
I forgot replace has a count parameter!
def alternate():
yield 'yes'
yield 'no'
#generator
YN = alternate()
sample = '!A!A'.replace('!A',next(YN), 1)
newsample = sample.replace('!A',next(YN), 1) # don't need count herereplace does not overwrite the original string, i.e. sample
Posts: 1,301
Threads: 151
Joined: Jul 2017
Amazing what one thinks of whilst cycling!
def alternate():
for i in range(5):
yield 'yes'
yield 'no'
YN = alternate()
for duh in YN:
print('!A!A'.replace('!A', duh, 1).replace('!A',next(YN)))I'll stop now!
|