illiterate
illiterate

Reputation: 319

Why the message is "name is not defined" rather than "variable referenced before assignment" in global scope?

One unreachable assignment statement made one "defined but not assigned" name in local scope but this is not for global scope:

#!/usr/bin/python3
#global scope
if False:
 baz = 4
 pass
#Raise "NameError: name 'baz' is not defined"
print(baz)

I expect get the message similar to variable 'baz' referenced before assignment in global scope as in local scope but actual message is name 'baz' is not defined in global scope.

I running in Python 3.7.2+.

Upvotes: 1

Views: 1219

Answers (2)

user2357112
user2357112

Reputation: 280301

In a function scope, Python analyzes all assignment operations to produce a complete list of the variables that scope should have. A local variable lookup is known at bytecode compilation time to correspond to at least one actual assignment to that variable in the function body, so the exception message for an unbound local variable mentions assignments.

No such analysis happens at global or class scope, and no such analysis could possibly be comprehensive, due to operations like from whatever import * and globals().update(stuff) that bind variables unknown at compile time. Python makes no attempt to keep track of what variables the global scope "should" have, and it doesn't try to distinguish between

print(a)
a = 1

where the variable is used before binding, and

print(b)

where there is no binding operation at all, or

thing = 1
print(thinh)

where thinh is a typo. The same error message template is used whether or not there's an assignment, so it wouldn't make as much sense for the template to say "before assignment" when there might not be an assignment at all.

Upvotes: 2

Barb
Barb

Reputation: 437

When you see NameError:, Python is trying to use a variable or function based on a previous definition. If you don't define your variable you will get this error.

In your code because your variable is only defined when you have declared something False Python can not pass it through globally to the rest of your code. You can make baz global by defining it before your false statement. There are a number of ways to achieve it however it is dependent on what your goal is. Here is an example:

baz = 0

if False:
    baz = 4

print(baz)

Output: 0

Then when True:

baz = 0

if True:
    baz = 4

print(baz)

Output: 4

Upvotes: 0

Related Questions