3

I'm trying to generate data for a matplotlib animation.
I have a data_gen function for matplotlib's "animation.FuncAnimation" function that is called like this:

ani = animation.FuncAnimation(fig, update, frames=data_gen, init_func=init, interval=10, blit=True)

My code has this form:

def func(a):
    a += 1
    return a

b = 0

def data_gen():
    global b
    c = func(b)
    b = c
    yield c

Unfortunately, this does not do what I want! For example,

print(data_gen().__next__())
print(data_gen().__next__())
print(data_gen().__next__())

for k in data_gen():
    print(k)

... produces this output:

1
2
3
4

I was expecting that the for loop would run forever, but it does not. (It stops at 4.)

The behavior I need is:

(1) set initial value for b

(2) update b each time the generator runs

All suggestions greatly appreciated!

Community
  • 1
  • 1
Riccati
  • 461
  • 4
  • 13

3 Answers3

2

Each time you call data_gen() in sets up a new generator, you just need to keep using the same generator object. There is also no reason do explicitly maintain a global state, that is what the generator does for you:

def data_gen(init_val):
    b = init_val
    while True:
        b += 1
        yield b

gen = data_gen(3)
print next(gen)
print 'starting loop'
for j in gen:
    print j
    if j > 50:
        print "don't want to run forever, breaking"
        break
tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • still wont work since there is no loop in the generator. it will only yield once. – M4rtini Dec 19 '13 at 21:52
  • @M4rtini Your right, got distracted by the other problems and confused by the global state.... – tacaswell Dec 19 '13 at 22:02
  • @tcaswell This is very helpful; however, including arguments to data_gen does not seem to work in the animation.FuncAnimation function call. I will ask another question if I can narrow down the source of the trouble. Thanks again. – Riccati Dec 19 '13 at 22:37
  • You should be calling it like `FuncAnimation(..., frames=gen_data(3),...)`. What errors does it give you? – tacaswell Dec 19 '13 at 22:39
  • @tcaswell Well... this is getting quite far away from the original question, but the error is: TypeError: object of type 'generator' has no len() This occurs in matplotlib\animation.py "self.save_count = len(frames)" – Riccati Dec 19 '13 at 22:45
  • ah, I just fixed that bug.... bug: https://github.com/matplotlib/matplotlib/issues/1769 PR: https://github.com/matplotlib/matplotlib/pull/2634 and it hasn't been merged into master yet... – tacaswell Dec 19 '13 at 22:49
  • @tcaswell Wow! I can't believe I ran into a bug that's not my fault. Thanks for your help. – Riccati Dec 20 '13 at 00:05
0

When I add an infinite loop into data_gen like this:

b=0
def data_gen():
    global b
    while True:
        b+=1
        yield b

I get (I use python 3.3, but the result should be the same for 2.x)

next(data_gen())
> 1
next(data_gen())
>2
next(data_gen())
>3

list(zip(range(10), data_gen()))
> [(0, 4), (1, 5), (2, 6), (3, 7), (4, 8), (5, 9), (6, 10), (7, 11), (8, 12), (9, 13)]

And finally if I do

for i in data_gen():
    print(i)

the code goes on and on printing numbers

Francesco Montesano
  • 8,485
  • 2
  • 40
  • 64
0
def func(a):
    a += 1
    return a

b = 0

def data_gen():
    global b
    while 1:
          c = func(b)
          b = c
          yield c

>>> gen.next()
    1
>>> gen.next()
    2
>>> gen.next()
    3
>>> gen.next()
    4
>>> gen.next()
    5
tuds
  • 131
  • 4