
Python Scope
A variable is only available from inside the region it is created. This is called scope.
Local Scope
A variable created inside a function belongs to the local scope of that function, and can only be used inside that function.
Example
A variable created inside a function is available inside that function:
def myfunc():
x = 300
print(x)
myfunc()Function Inside Function
As explained in the example above, the variable x is not available outside the function, but it is available for any function inside the function:
Example
The local variable can be accessed from a function within the function:
def myfunc():
x = 300
def myinnerfunc():
print(x)
myinnerfunc()
myfunc()Global Scope
A variable created in the main body of the Python code is a global variable and belongs to the global scope.
Global variables are available from within any scope, global and local.
Example
A variable created outside of a function is global and can be used by anyone:
x = 300
def myfunc():
print(x)
myfunc()
print(x)Naming Variables
If you operate with the same variable name inside and outside of a function, Python will treat them as two separate variables, one available in the global scope (outside the function) and one available in the local scope (inside the function):
Example
The function will print the local x, and then the code will print the global x:
x = 300
def myfunc():
x = 200
print(x)
myfunc()
print(x)Global Keyword
If you need to create a global variable, but are stuck in the local scope, you can use the global keyword.
The global keyword makes the variable global.
Example
If you use the global keyword, the variable belongs to the global scope:
def myfunc():
global x
x = 300
myfunc()
print(x)Also, use the global keyword if you want to make a change to a global variable inside a function.
Example
To change the value of a global variable inside a function, refer to the variable by using the global keyword:
x = 300
def myfunc():
global x
x = 200
myfunc()
print(x)Nonlocal Keyword
The nonlocal keyword is used to work with variables inside nested functions.
The nonlocal keyword makes the variable belong to the outer function.
Example
If you use the nonlocal keyword, the variable will belong to the outer function:
def myfunc1():
x = "Jane"
def myfunc2():
nonlocal x
x = "hello"
myfunc2()
return x
print(myfunc1())The LEGB Rule
Python follows the LEGB rule when looking up variable names, and searches for them in this order:
- Local - Inside the current function
- Enclosing - Inside enclosing functions (from inner to outer)
- Global - At the top level of the module
- Built-in - In Python's built-in namespace
Example
Understanding the LEGB rule:
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print("Inner:", x)
inner()
print("Outer:", x)
outer()
print("Global:", x)Python Decorators
Decorators let you add extra behavior to a function, without changing the function's code.
A decorator is a function that takes another function as input and returns a new function.
Basic Decorator
Define the decorator first, then apply it with @decorator_name above the function.
Example
A basic decorator that uppercases the return value of the decorated function:
def changecase(func):
def myinner():
return func().upper()
return myinner
@changecase
def myfunction():
return "Hello Sally"
print(myfunction())By placing @changecase directly above the function definition, the function myfunction is being "decorated" with the changecase function.
Multiple Decorator Calls
A decorator can be called multiple times. Just place the decorator above the function you want to decorate.
Example
Using the @changecase decorator on two functions:
def changecase(func):
def myinner():
return func().upper()
return myinner
@changecase
def myfunction():
return "Hello Sally"
@changecase
def otherfunction():
return "I am speed!"
print(myfunction())
print(otherfunction())Arguments in the Decorated Function
Functions that require arguments can also be decorated, just make sure you pass the arguments to the wrapper function:
Example
Functions with arguments can also be decorated:
def changecase(func):
def myinner(x):
return func(x).upper()
return myinner
@changecase
def myfunction(nam):
return "Hello " + nam
print(myfunction("John"))*args and **kwargs
Sometimes the decorator function has no control over the arguments passed from decorated function, to solve this problem, add (*args, **kwargs) to the wrapper function, this way the wrapper function can accept any number, and any type of arguments, and pass them to the decorated function.
Example
Secure the function with *args and **kwargs arguments:
def changecase(func):
def myinner(*args, **kwargs):
return func(*args, **kwargs).upper()
return myinner
@changecase
def myfunction(nam):
return "Hello " + nam
print(myfunction("John"))Decorator With Arguments
Decorators can accept their own arguments by adding another wrapper level.
Example
A decorator factory that takes an argument and transforms the casing based on the argument value:
def changecase(n):
def changecase(func):
def myinner():
if n == 1:
a = func().lower()
else:
a = func().upper()
return a
return myinner
return changecase
@changecase(1)
def myfunction():
return "Hello Linus"
print(myfunction())Multiple Decorators
You can use multiple decorators on one function.
This is done by placing the decorator calls on top of each other.
Decorators are called in the reverse order, starting with the one closest to the function.
Example
One decorator for upper case, and one for adding a greeting:
def changecase(func):
def myinner():
return func().upper()
return myinner
def addgreeting(func):
def myinner():
return "Hello " + func() + " Have a good day!"
return myinner
@changecase
@addgreeting
def myfunction():
return "Tobias"
print(myfunction())Preserving Function Metadata
Functions in Python has metadata that can be accessed using the __name__ and __doc__ attributes.
Example
Normally, a function's name can be returned with the __name__ attribute:
def myfunction():
return "Have a great day!"
print(myfunction.__name__)