10

Why does this code work:

var = 0
def func(num):
 print num
 var = 1
 if num != 0:
 func(num-1)
func(10)

but this one gives a "local variable 'var' referenced before assignment" error:

var = 0
def func(num):
 print num
 var = var
 if num != 0:
 func(num-1)
func(10)
asked Oct 26, 2012 at 17:08
2

6 Answers 6

9

Because in the first code, you have created a local variable var and used its value, whereas in the 2nd code, you are using the local variable var, without defining it.

So, if you want to make your 2nd function work, you need to declare : -

global var

in the function before using var.

def func(num):
 print num
 var = 1 <-- # You create a local variable
 if num != 0:
 func(num-1)

Whereas in this code:

def func(num):
 print num
 var = var <--- # You are using the local variable on RHS without defining it
 if num != 0:
 func(num-1)

UPDATE: -

However, as per @Tim's comment, you should not use a global variable inside your functions. Rather deifine your variable before using it, to use it in local scope. Generally, you should try to limit the scope of your variables to local, and even in local namespace limit the scope of local variables, because that way your code will be easier to understand.

The more you increase the scope of your variables, the more are the chances of getting it used by the outside source, where it is not needed to be used.

answered Oct 26, 2012 at 17:10
Sign up to request clarification or add additional context in comments.

10 Comments

or, better yet, don't use global variables in the first place :)
@TimPietzcker. Ok. Can you please specify a specific reason for that?
No, he's using the local variable on the RHS in the second example, which is why it's an error; it's not defined yet.
@RohitJain: Some reasons not to use global variables: c2.com/cgi/wiki?GlobalVariablesAreBad (but it's worth noting that in Python, your top-level functions and classes are actually global variables, which is an example of why you don't want that as a hard and fast rule, but as a heuristic).
@abarnert. Thanks :) Will take a look at the link :)
|
6

If you have var = ... anywhere in a function, the name "var" will be treated as a local variable for the entire function, regardless of where that assignment occurs. This means that all occurrences of var in your function will be resolved in the local scope, so the right hand side of var = var results in the referenced before assignment error because var has not yet been initialized in the function's scope.

answered Oct 26, 2012 at 17:11

6 Comments

This surprised me, too. I would have assumed that func would be a closure over var, and that the var = var line would have created a function-local variable, var, and assigned it the value of the module-level var. The "anywhere in a function" part of your answer smells magical to me. Surely that's not the actual cause?
@KirkStrauser: it is somewhat magical. The scope of names is static, unlike just about everything else.
@KirkStrauser: Python doesn't really have variables in the sense you're thinking of; it has name bindings. For most simple cases, the effect is the same, but it does mean that some cases are confusing until you understand the difference. In particular, if you've learned the rules for "how closures work in dynamic languages" from Javascript, you're going to be thrown off by Python.
@abarnert Actually, I learned that all in Python. I'm familiar with name bindings, "pass by object reference", etc. It's just that I hadn't seen this case before and it isn't as I would have expected.
Now that I've read a little more, to expand on F.J's answer: variables are added to a function's list of local variables (in the co_varnames attribute) at compilation time if they are used on the left-hand side of an assignment. This leads to (to me!) interesting situations like def foo(): var = var failing but def foo(): exec('var = var') being perfectly fine. I'd describe this as more of an implementation detail of an optimization pass than a feature of the language itself.
|
1

You can read a global without declaring it global. But to write a global, you need to declare it global.

answered Oct 26, 2012 at 17:36

1 Comment

This isn't the OP's problem. True, his first function may not do what he hoped, but he's asking why the second function raises an exception. And "You can read a global without declaring it global" is exactly what's confusing him: he can't read the global var without declaring it global in this case, because he's got a local name that overshadows it.
0

In your second piece of code you have created a local variable in RHS and without defining it, you are assigning it to the LHS variable var which is global (a variable defined outside the function is considered global explicitly).

If your intention is to create a local variable inside the function and assign it to the value of the global variable, this will do the trick:

var = 0
def func(num):
 print num
 func.var = var # func.var is referring the local
 # variable var inside the function func
 if num != 0:
 func(num-1)
func(10)
fenceop
1,5373 gold badges19 silver badges30 bronze badges
answered Nov 25, 2014 at 6:32

Comments

-1
def runscan(self):
 p = os.popen('LD_PRELOAD=/usr/libv4l/v4l1compat.so zbarcam
 /dev/video0','r')
def input(self):
 self.entryc.insert(END, code)

how about this? i want use local 'code' to the next function to insert the result of barcode to my Tkinter entryBox.. Thanks

answered Jan 6, 2017 at 19:26

1 Comment

This looks like you're asking a new/unrelated question to the original post. Consider posting this as a new question.
-3

Each function block is a local scope. If you want to assign to global variables, you need to do so explicitly:

var = 0
def func(num):
 print num
 global var
 var = 1
 if num != 0:
 func(num-1)
print var # 0
func(2)
print var # 1
answered Oct 26, 2012 at 17:11

5 Comments

This implies that the OP's first example shouldn't work either, and yet it does. Plus, your example doesn't even use the global var.
I don't even know what you're reading at this point. The OP's first example does not throw an exception—in fact, that's the whole reason he came here asking this question.
The question was about the second example, not the first. There's no reason for the first to throw any exceptions... @RohitJain explained why the second example throws an exception. I'm still not sure why you think this answer implies that the first example shouldn't work.
It feels like you're trying to score points, rather than give useful information. You've removed one comment and edited your answer in ways that make my comments seem senseless, but your answer still doesn't address the OP's confusion at all, or explain anything that's missing from the two existing useful answers. I'm done commenting here.
The OP's purpose in the second function is ambiguous: he could be trying to read the global var, or he could be trying to set it, or both. Since he didn't provide any additional input since asking the question, neither of us know for sure what he was trying to achieve. I assumed the case of trying to set the global var, and you assumed the other. I edited the answer to make it clearer, and removed my first comment because it wasn't constructive. And by the way, this entire comment thread isn't very constructive either... So lets just stop.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.