What is Scope Resolution in Python?
Sometimes objects within the same scope have the same name but function differently. In
such cases, scope resolution comes into play in Python automatically. A few examples of
such behaviour are:
• Python modules namely 'math' and 'cmath' have a lot of functions that are common to both of
them - log10(), acos(), exp() etc. To resolve this amiguity, it is necessary to prefix them with
their respective module, like math.exp() and cmath.exp().
• Consider the code below, an object temp has been initialized to 10 globally and then to 20 on
function call. However, the function call didn't change the value of the temp globally. Here, we
can observe that Python draws a clear line between global and local variables treating both
their namespaces as separate identities.
temp = 10 # global-scope variable
def func():
temp = 20 # local-scope variable
print(temp)
print(temp) # output => 10
func() # output => 20
print(temp) # output => 10
This behaviour can be overriden using the global keyword inside the function, as shown in the
following example:
temp = 10 # global-scope variable
def func():
global temp
temp = 20 # local-scope variable
print(temp)
print(temp) # output => 10
func() # output => 20
print(temp) # output => 20
10. What are decorators in Python?
Decorators in Python are essentially functions that add functionality to an existing function in
Python without changing the structure of the function itself. They are represented by
the @decorator_name in Python and are called in bottom-up fashion. For example:
# decorator function to convert to lowercase
def lowercase_decorator(function):
def wrapper():
func = function()
string_lowercase = func.lower()
return string_lowercase
return wrapper
# decorator function to split words
def splitter_decorator(function):
def wrapper():
func = function()
string_split = func.split()
return string_split
return wrapper
@splitter_decorator # this is executed next
@lowercase_decorator # this is executed first
def hello():
return 'Hello World'
hello() # output => [ 'hello' , 'world' ]
The beauty of the decorators lies in the fact that besides adding functionality to the output of
the method, they can even accept arguments for functions and can further modify those
arguments before passing it to the function itself. The inner nested function, i.e. 'wrapper'
function, plays a significant role here. It is implemented to enforce encapsulation and thus,
keep itself hidden from the global scope.
# decorator function to capitalize names
def names_decorator(function):
def wrapper(arg1, arg2):
arg1 = arg1.capitalize()
arg2 = arg2.capitalize()
string_hello = function(arg1, arg2)
return string_hello
return wrapper
@names_decorator
def say_hello(name1, name2):
return 'Hello ' + name1 + '! Hello ' + name2 + '!'
say_hello('sara', 'ansh') # output => 'Hello Sara! Hello Ansh!'