Lecture 25-26 - Global and Local Scopes
Lecture 25-26 - Global and Local Scopes
That object can be accessed using that name in various parts of our code But not just
anywhere!
That variable name and it's binding (name and object) only "exist" in specific parts of our
code
the portion of code where that name/binding is defined, is called the lexical scope of the variable these bindings are
stored in namespaces
There is no concept of a truly global (across all the modules in our entire app) scope in Python. The only
exception to this are some of the built-in globally available objects, such as:
The built-in and global variables can be used anywhere inside our module including
Module2
Scope name
space
If you reference a variable name inside a scope and Python does not find it in that scope's namespace it will
look for it in an enclosing scope's namespace
Examples
module1.py Python does not find True or print in the current (module/global) scope So, it looks for
print(True) them in the enclosing scope →built-in
Finds them there → True
module2.py Python does not find a or print in the current (module/global) scope
print(a) So, it looks for them in the enclosing scope →built-in
e.g. a = 10
Variables defined inside a function are not created until the function is called
Variables defined inside the function are assigned to that scope → Function Local scope
→ Local scope
my_func
a→ 'z'
my_func('z', 2) b→ 2
c→ same names, different local scopes
'zz'
my_func
my_func(10, 5) a→ 10
b→ 5
c→
50
Nested Scopes
Namespace lookups
Scopes are often nested When requesting the object bound to a variable name:
e.g. print(a)
Built-in Scope
a = 10 a→ 10
global scope
def my_func(b): my_func
print(True) print(a)
print(b) local
b→ 300 local
scope b→ 'a'
scope
my_func(300)
my_func('a')
What about modifying a global variables value from inside the function?
print(a) → 0 local
a→ 100
The global keyword
We can tell Python that a variable is meant to be scoped in the global scope by using the global keyword
a=0
counter = 0
def increment():
global counter
counter += 1
increment()
increment()
increment()
print(counter) → 3
Global and Local Scoping
When Python encounters a function definition at compile-time
it will scan for any labels (variables) that have values assigned to them (anywhere in the function) if the label has
not been specified as global, then it will be local
variables that are referenced but not assigned a value anywhere in the function will not be local, and Python will, at run-
time, look for them in enclosing scopes
a = 10 Assignment
def func4(): at compile time → a local
a is referenced only in entire function
at compile time → a non-local print(a) a =
def func1():
100
print(a)
assignment → when we call func4()
def func2(): a = at compile time → a local print(a) results in a run-time error
100
because a is local, and we are
referencing it before we have assigned
def func3(): assignment a value to it!
global a a = at compile time → a global
100 (because we told Python a was global)
Inner Functions
We can define functions from inside another function:
inner_func()
local (inner_func)
outer_func()
Both functions have access to the global and built-in scopes as well as their respective local scopes
But the inner function also has access to its enclosing scope – the scope of the outer function That scope is neither
module1.py a = 10
def outer_func():
print(a)
def outer_func():
a = 10
def inner_func():
print(a)
inner_func()
outer_func()
When inner_func is called, Python does not find a in the local (inner_func) scope So it looks for it in the
a = 10
def outer_func():
def inner_func():
print(a)
inner_func()
outer_func()
When inner_func is called, Python does not find a in the local (inner_func) scope So it looks for it in the
enclosing scope, in this case the scope of outer_func
Since it does not find it there either, it looks in the enclosing (global) scope
Modifying global variables
We saw how to use the global keyword in order to modify a global variable within a nested scope
a = 10
def outer_func1():
global a
a = 1000
outer_func1()
print(a) → 1000
We can of course do the same thing from within a nested function
def outer_func():
x = 'hello'
def inner_func():
x = 'python'
inner_func()
print(x)
outer_func() → hello
Just as with global variables, we have to explicitly tell Python we are modifying a nonlocal variable We can do
def inner_func():
nonlocal x
x = 'python'
inner_func()
print(x)
outer_func() → python
Nonlocal Variables
Whenever Python is told that a variable is nonlocal
it will look for it in the enclosing local scopes chain until it first encounters the specified variable
name
Beware: It will only look in local scopes, it will not look in the global scope
CS504 Software Engineering
def outer(): Virtual University of Pakistan · Playlist
x = 'hello' global
Virtual University of Pakistan · Playlist
Verified
def inner1(): • local (outer) inner1
def inner2(): • x
nonlocal x local (inner1)
inner2
x = 'python' inner2()
local (inner2)
x
inner1()
print(x)
outer() → python
Nonlocal Variables
But consider this example:
global
→ python
def outer():
x = 'hello' local (outer)→ montyx
def inner1():
x = 'python' local (inner1)
x
→ hello
def inner2():
nonlocal x local (inner2)
x = 'monty' x
print('inner(before)', x) inner2() → python
print('inner(after)', x)
→ monty
inner1() print('outer', x)
outer() → monty
Nonlocal Variables
→ monty
inner1()
print('outer', x) → monty
outer()
Nonlocal and Global Variables
global
x = 100
def outer(): x
local (outer)
x = 'python' x
def inner1(): nonlocal x
local (inner1) x
x = 'monty'
def inner2(): local (inner2)
global x x
x = 'hello' print('inner(before)', x)
inner2()
print('inner(after)', x) → monty
→ monty
inner1()
print('outer', x) → monty
outer() print(x)
→ hello