2

So I am making a generator from a list but would like to call next on it, which should just return the next item in the list, however it returns the same object, i.e. the whole piece of code is run again in stead of just returning the yield part. The example below shows the expected behaviour when looping through the list, but then the next returns 1 twice, whereas I would like the second call of next to return 2.

class demo:
    @property
    def mygen(self):
        a = [1,2,3,4,5]
        b = [6,7,8,9,10]
        yield from a
        yield from b

if __name__=='__main__':
    demo1 = demo()
    print([_ for _ in demo1.mygen])
    demo2 = demo()
    print(next(demo2.mygen))
    print(next(demo2.mygen))

There's a reason I am turning a list into a generator as it is the response from an api call and would like to dynamically return the next item in the list and make the api call if it comes to the end of that list.

martineau
  • 119,623
  • 25
  • 170
  • 301
RexFuzzle
  • 1,412
  • 2
  • 17
  • 30

1 Answers1

7

Every call to the property creates a new generator. You should store the generator returned by the property to a variable. Then you will be able to call next multiple times. Change

print(next(demo2.mygen))
print(next(demo2.mygen))  # calls next on a fresh generator

to

gen = demo2.mygen
print(next(gen))
print(next(gen))  # calls next on the SAME generator

As others have pointed out, this behaviour should have you reconsider making this a property in the first place. Seeing

demo2.mygen()

makes it much more obvious that there is some dynamic stuff going on, while

demo2.mygen

gives the impression of a more static attribute producing the same object every time. You can find some more elaboration on that here.

user2390182
  • 72,016
  • 6
  • 67
  • 89