0

I'm learning Python and ran this piece of code in the python console earlier today:

num = 0

def generator():
    while True:
        yield num
        num += 1

for i in generator():
    if i > 5: break
    print(i)

It threw a UnboundLocalError: local variable 'num' referenced before assignment

I re-wrote the code and this version worked:

def generator():
    num = 0
    while True:
        yield num
        num += 1

for i in generator():
    if i > 5: break
    print(i)

My question is this: Can you not use local variables inside generator functions like you can with regular functions?

Vinayak
  • 1,103
  • 3
  • 18
  • 40
  • 2
    `num` is not local to your function in the failing code – UnholySheep Sep 10 '16 at 20:37
  • @UnholySheep if I define a function, `test()` with `print(num)` inside it and call `test()` in the console, it prints out 0. – Vinayak Sep 10 '16 at 20:40
  • 2
    @Vinayak from the accepted answer of the linked question: "If you want to simply access a global variable you just use its name. However to change its value you need to use the global keyword." – Mephy Sep 10 '16 at 20:41
  • 1
    @Vinayak if your `test()` function were to do `num += 1` you would get the same error (see the question @Mephy linked) – UnholySheep Sep 10 '16 at 20:42
  • 3
    Note that this has nothing to do with generator functions. If you remove the `yield` from your first example, you'll see the same error. – BrenBarn Sep 10 '16 at 20:42
  • @Mephy that explains it. Thank you! – Vinayak Sep 10 '16 at 20:48
  • @Vinayak - Consider accepting one of the given answers, even if the comments were clear enough. – linusg Sep 10 '16 at 20:51
  • @linusg Done. I was waiting for the time limit before I could accept answers to expire. – Vinayak Sep 10 '16 at 20:53
  • Ah I see :). One needs to wait too long sometimes IMO. – linusg Sep 10 '16 at 20:54

2 Answers2

1

In the first code, you attempt to use num as a global variable: It is defined outside the function.

When the program reaches num += 1, you then attempt to assign to a local variable which happens to have the same name as the global that you referenced earlier. But since a local variable called num hasn't be assigned a value yet, the increment fails.

If you want to assign or increment a global variable inside a function, it must be declared with global num (usually right at the start of the function). This has nothing to do with generators, it would fail for regular functions too.

James K
  • 3,692
  • 1
  • 28
  • 36
1

As UnholySheep has commented, the num variable is not locally defined inside the generator() function.

Just mark that you use it from the global namespace inside the generator() function, using the global keyword:

num = 0

def generator():
    global num
    while True:
        yield num
        num += 1

for i in generator():
    if i > 5: break
    print(i)

...and everything should be fine.

Note: The issue is not related to the type of function (generator including yield) you're using.

Graham
  • 7,431
  • 18
  • 59
  • 84
linusg
  • 6,289
  • 4
  • 28
  • 78