Python Programming/Scoping
Variables
[edit | edit source]Variables in Python are automatically declared by assignment. Variables are always references to objects, and are never typed. Variables exist only in the current scope or global scope. When they go out of scope, the variables are destroyed, but the objects to which they refer are not (unless the number of references to the object drops to zero).
Scope is delineated by function and class blocks. Both functions and their scopes can be nested. So therefore
deffoo():defbar():x=5# x is now in scopereturnx+y# y is defined in the enclosing scope latery=10returnbar()# now that y is defined, bar's scope includes y
Now when this code is tested,
>>>foo()15>>>bar()Traceback(mostrecentcalllast):File"<pyshell#26>",line1,in-toplevel-bar()NameError:name'bar'isnotdefined
The name 'bar' is not found because a higher scope does not have access to the names lower in the hierarchy.
It is a common pitfall to fail to assign an object to a variable before use. In its most common form:
>>>forxinrange(10):y.append(x)# append is an attribute of listsTraceback(mostrecentcalllast):File"<pyshell#46>",line2,in-toplevel-y.append(x)NameError:name'y'isnotdefined
Here, to correct this problem, one must add y = [] before the for loop executes.
A loop does not create its own scope:
forxin[1,2,3]:inner=xprint(inner)# 3 rather than an error
Keyword global
[edit | edit source]Global variables of a Python module are read-accessible from functions in that module. In fact, if they are mutable, they can be also modified via method call. However, they cannot be modified by a plain assignment unless they are declared global in the function.
An example to clarify:
count1=1count2=1list1=[]list2=[]deftest1():print(count1)# Read access is unproblematic, referring to the globaldeftest2():try:print(count1)# This try block is problematic because...count1+=1# count1 += 1 causes count1 to be local but local version is undefined.exceptUnboundLocalErroraserror:print("Error caught:",error)deftest3():list1=[2]# No outside effect; this defines list1 to be a local variabledeftest4():globalcount2,list2print(count1)# Read access is unproblematic, referring to the globalcount2+=1# We can modify count2 via assignmentlist1.append(1)# Impacts the global list1 even without global declaration since its a method calllist2=[2]# We can modify list2 via assignment test1()test2()test3()test4()print("count1:",count1)# 1print("count2:",count2)# 2print("list1:",list1)# [1]print("list2:",list2)# [2]
Links:
- 6.13. The global statement, docs.python.org
- What are the rules for local and global variables in Python? in Programming FAQ, docs.python.org
Keyword nonlocal
[edit | edit source]Keyword nonlocal, available since Python 3.0, is an analogue of global for nested scopes. It enables a nested function to assign-modify even an immutable variable that is local to the outer function.
An example:
# Requires Python 3defouter():outerint=0outerint2=10definner():nonlocalouterintouterint=1# Impacts outer's outerint only because of the nonlocal declarationouterint2=1# No impactinner()print(outerint)print(outerint2)outer()
Simulation of nonlocal in Python 2 via a mutable object:
defouter():outerint=[1]# Technique 1: Store int in a listclassouterNL:pass# Technique 2: Store int in a classouterNL.outerint2=11definner():outerint[0]=2# List members can be modifiedouterNL.outerint2=12# Class members can be modifiedinner()print(outerint[0])print(outerNL.outerint2)outer()
Links:
- 7.13. The nonlocal statement, docs.python.org
globals and locals
[edit | edit source]To find out which variables exist in the global and local scopes, you can use locals() and globals() functions, which return dictionaries:
int1=1deftest1():int1=2globals()["int1"]=3# Write access seems possibleprint(locals()["int1"])# 2test1()print(int1)# 3
Write access to locals() dictionary is discouraged by the Python documentation.
Links:
- 2. Built-in Functions # globals, docs.python.org
- 2. Built-in Functions # locals, docs.python.org
External links
[edit | edit source]- 4. Execution model, docs.python.org
- 7.13. The nonlocal statement, docs.python.org
- PEP 3104 -- Access to Names in Outer Scopes, python.org