1

I experience something strange from my point of view

I need to generate alternatively True and False values like this:

False, True, False, False, True, True, False, False, False, True, True, True, False, False, False, False, True, True, True, True, ...

I need to get one False, one True, then two False, two True, then three False, three True, etc

In my mind, using the yield keyword in a function was a good way to achive this:

def generateFalseTrueRangesAlternatively(limit):
    limitForChange = 0
    index = 0
    rv = True
    for i in range(0, limit):
        if index == limitForChange:
            rv = not rv 
            index = 0
            if not rv:
                limitForChange += 1
        index += 1
        yield rv

for i in range(0,4):
    g =  generateFalseTrueRangesAlternatively(20)
    print(next(g))

But I get only False values:

False
False
False
False

As a workaround, I wrote the following code, which generates a list :

def generateFalseTrueRangesAlternativelyList(limit):
    limitForChange = 1
    index = 0
    rv = False
    out = []
    for i in range(0, limit):
        if index == limitForChange:
            rv = not rv 
            index = 0
            if not rv:
                limitForChange += 1
        index += 1
        out.append(rv)
    return out
l = generateFalseTrueRangesAlternativelyInList(6)
for i in range (0,6):
    print(l[i])

Which outputs:

False
True
False
False
True
True

Questions

What is wrong with my generateFalseTrueRangesAlternatively function ?

How could it be modified to behave like the generateFalseTrueRangesAlternativelyInList but without creating a list ?

Is there something I did not understand with yield usage and what ?

Actually, my curiosity needs to be satisfied by answering this fundamental question: why ?

(My Python version: 3.5.4)

lauhub
  • 894
  • 1
  • 15
  • 27
  • 2
    side note: [camelCase is generally frowned upon in Python](https://stackoverflow.com/questions/159720/what-is-the-naming-convention-in-python-for-variable-and-function-names) – TemporalWolf Oct 19 '17 at 23:06
  • @cᴏʟᴅsᴘᴇᴇᴅ it is a pity that you deleted your answer as it seemed to be much more pythonic than my code. Thanks for your suggestion – lauhub Oct 19 '17 at 23:25

3 Answers3

5

In the first snippet, you should only call the generator once, outside the for-loop, then use the next calls to obtain successive yielded values:

g = generateFalseTrueRangesAlternatively(20)
for i in range(4):
    print(next(g))

Also note you can omit the lower bound of the range if it is zero.

Lawrence D'Oliveiro
  • 2,768
  • 1
  • 15
  • 13
5

You code is fine; the usage of generator is wrong.

Just iterate it:

for i in generateFalseTrueRangesAlternatively(20):
    print(i)
Uriel
  • 15,579
  • 6
  • 25
  • 46
0

I'd suggest a simplified implementation like this because it's much easier to understand and your original generateFalseTrueRangesAlternatively doesn't yield the correct values:

def alternate_trues_and_falses(limit):
    for i in range(1, limit + 1):
        for j in range(i):
            yield True
        for j in range(i):
            yield False

>>> list(alternate_trues_and_falses(2))
[True, False, True, True, False, False]

>>> for value in alternate_trues_and_falses(2):
...     print(value)
...
True
False
True
True
False
False