1

Possible Duplicate:
Python variable scope question

The Python Manual defines the scope as:

A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.

I have this program:

import random
def f():
  a = "Is the scope static?"
  if random.randint(0, 1) == 1:
    del a
  print a

There is a 50% chance that the print will fail:

>>> f()
Is the scope static?
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in f
UnboundLocalError: local variable 'a' referenced before assignment

By that, I think that there is a 50% chance that the print statement is outside the scope of 'a', but I can be wrong. What is the "correct" interpretation of scope in Python? Is the scope of a variable in Python defined statically? What is the scope of the variable "a"?

Community
  • 1
  • 1
vz0
  • 32,345
  • 7
  • 44
  • 77
  • 1
    @Blender There is a 50% chance that the name is not visible. – vz0 Oct 15 '12 at 22:15
  • 3
    Scope is only defined on variables that exist. That `del` statement affects `a` during run-time, not while the script is being parsed by the interpreter. – Blender Oct 15 '12 at 22:20
  • 1
    @vz0 As Blender says, at time of definition the scope of a is local to the function f. There is a 50% chance that it has been explicitly removed from the namespace by the del statement, but that is different from it being not visible due to calling for it outside of its scope. – TimothyAWiseman Oct 15 '12 at 22:41
  • @TimothyAWiseman Different in what sense? If it is removed from the namespace, it is not in scope. – vz0 Oct 15 '12 at 22:57
  • @vz0 Ben's answer explains that better than I could have, but one way to think of it that might help: Something is out of scope if it was defined in one area and execution left that area. Here you didn't leave the area it was defined, you specifically instructed the interpreter to remove it form the namespace. – TimothyAWiseman Oct 16 '12 at 16:42
  • Possible duplicate of [Python variable scope error](https://stackoverflow.com/questions/370357/python-variable-scope-error) – Cœur Jul 14 '18 at 14:34

3 Answers3

11

The scope of the name a is over the entirety of the function f, and is purely static. It is not at all correct to say that "there is a 50% chance that the print statement is outside the scope of a". "Not in scope" is not the only reason why a name lookup can fail.

Note the error you get from this function:

>>> def foo():
...   print a
... 
>>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in foo
NameError: global name 'a' is not defined

It's not the same error you get when your function has executed del a. In my foo, a was not defined in the local scope of foo, so name lookup proceeded to the global scope, where a wasn't found either, so we get an exception about there not being a global a.

The error you get clearly states that Python is aware that the name a is a local variable of f. However it has no value, because you deleted it. (Normally this would only happen because you try to read a local variable before you've ever written to it, which is why the error message is worded the way it is)

Note also this case:

a = 3
>>> def bar():
...   a = 1
...   del a
...   print a
... 
>>> bar()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in bar
UnboundLocalError: local variable 'a' referenced before assignment

Python complains about the local a not having a value. If a were simply not in the local scope, it would have looked up a globally and found the 3:

>>> a = 8
>>> def baz():
...   print a
... 
>>> baz()
8

This is different behaviour than you get when you del things from the global scope:

>>> a = 12
>>> del a
>>> print a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

Here you get an exception as if a had never existed. The reason for the difference is because the local scope of a function is static. If a function contains an assignment to a name, then that name is locally scoped over the entirety of the function's body1. Even before the first assignment, or after you've used del to get rid of it, lookup of that name in that function will try to get the value of the local variable.


1 Unless the name has been declared global or nonlocal.

Ben
  • 68,572
  • 20
  • 126
  • 174
  • 1
    Nice answer, the difference between the undefined global and unassigned local messages is a good way to show what Python is doing behind the scenes to find the value of the variable. – Andrew Clark Oct 15 '12 at 23:05
3

Python follows LEGB rule:

L: Local          # Current def
E: Enclosing      # Any enclosing def
G: Global         # Globals
B: Built-in       # Built-ins

so for your question it's L.

Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
1

Only classes, functions, and modules provide scope in Python, if,while and other looping/branching constructs don't.

From the docs:

Scopes are determined statically but used dynamically. At any time during execution, there are at least three nested scopes whose namespaces are directly accessible:

the innermost scope, which is searched first, contains the local names
the scopes of any enclosing functions, which are searched starting with the nearest enclosing scope, contains non-local, but also non-global names
the next-to-last scope contains the current module’s global names
the outermost scope (searched last) is the namespace containing built-in names

In your code you define a in the local namespace and also remove it. Using del in if branch isn't in any way different than using it in somewhere else in your function.

root
  • 76,608
  • 25
  • 108
  • 120