USE OBJECTS FUNCTION
Before addressing the topic “Namespaces in Python” let’s have a few more thoughts on functions. If we use the round brackets after the function it means that we are calling the function, if we use only the name of the function in the program it means that we are referring to the function as an object whose instance belongs to the function class.
This means that functions are objects and are instances of the function class. Let’s see what the main features are in using functions as objects.
Nested functions
Let’s see an example of how functions can be nested within our programs.
FUNCTION AS RETURN VALUE
A function can be returned as a value. The nested function returns an object, the inner(a, b) function. We said that if we refer to the function only by its de facto name we are accessing the function as an object, we are not invoking it. We can return a function nested outside the function that created it outer() and invoke it. f points to a function, passing its arguments to it we can invoke the function returned as an object.
FUNCTION AS A PARAMETER
We can pass a function object as a parameter of an object of another function.
NAMESPACE AND SCOPE
Namespaces in Python are a mapping of names to objects. They are used to keep the names we assign to objects in different areas of the program distinct to avoid name collisions. In practice it serves to ensure the uniqueness of the names used in the programs. At runtime that is when a program is running there are multiple namespaces, they are organized in a hierarchical form. Namespaces have different life cycles.
THE SCOPE
When we talk about scope, that is, context, we mean an area of code where you are at a certain moment that determines which namespace should be used by Python for resolving object names.
HIERARCHY OF NAMESPACE
We have said that the namespaces are organized hierarchically, starting for the resolution of the names from the lower ones and then going up to the higher ones.
LOCAL SCOPE
The Local scope is the internal level of a function, the arguments and variables found within it form the Local Namespace. It is created when we invoke a function and is removed when the function returns. x, y and c are arguments and variables that form the Local Namespace of the sum function.
ENCLOSED SCOPE
If we move up one level, we find the Enclosed Scope. The inner() function nested in the outer(x) function is using two variables x and y. Python verifies these two variables goes up one level and finds them defined as a parameter and the other defined within the outer(x) function. Python going up the hierarchy is able to solve the x and y variables defined in the nested function. Assuming it failed to resolve the variables, it goes up one more level in what is called the Global Scope.
GLOBAL NAMESPACE
x which is 100 is a global variable because it is defined outside of all functions. When myFunc(y) is called, the y argument is resolved in the Namespace Local. For the variable x Python goes up to the source level and solves it. The last Namespace which is hierarchically the highest of all are the definitions of the predefined functions. It is provided directly from the Python runtime environment. Contains predefined functions as mentioned or Built-in eg print which we have used many times.
BUILT-IN NAMESPACE
Default Namespace that contains predefined functions in Python.
GLOBAL AND NONLOCAL
The global and nonlocal keywords are used to alter the namespace mechanism already seen. Before introducing them, let’s see the concept of information hiding.
INFORMATION HIDING
If a function defines a local variable already present at a higher level of the hierarchy, this hides the global variable. When exiting out of myFunc() print(x) will print the variable located in the global namespace. What we have seen is the standard Python behavior. This behavior can be altered by using the global and nonlocal keywords.
THE STATEMENT GLOBAL
The global statement causes the local variable x to become global. So print(x) will print 20 not 100. MyFunc() does not create a new global variable but uses the existing one. When we print the value 100 it will become 20.
THE STATEMENT NONLOCAL
The nonlocal statement acts in a similar way to global but in this case we access the namespace of an external function outer(). with nonlocal we declare that we want to use a variable y inside the inner() that is not local to this function but which is at a higher level of the hierarchy, that is, in outer().
FUNCTION DECORATOR
A Decorator is a function that takes as input a function as a parameter enriches it with instructions by adding its own code and then returns as a return value not the function passed in input but the decorator. All this serves to enrich the behavior of an existing function with code without modifying the original function.
def myDecorator(f): def decorator(): print('Ho decorato') f() return decorator @myDecorator def myFunc(): print('La Funzione myFunc') myFunc()
LAMBDA FUNCTIONS
In addition to the def statement, Python allows you to create a function with a lambda expression that generates a function object. Instead of assigning a name to the function with the def statement, the lambda function returns an anonymous function.
import math #ELEVAMENTO A POTENZA f=lambda x,y:math.pow(x,y) print(f(2,3)) #SENO DI UN NUMERO f=lambda v:math.sin(v) print(f(180)) #STAMPA LA RADICE QUADRATA DI UN NUMERO PASSATO COME ARGOMENTO f=lambda x:math.sqrt(x) print(f(144)) #CONCATENA DUE VALORI f=lambda s1,s2:s1+s2 print(f('Hello ','World!')) #FUNZIONI RICORSIVE CALCOLO DEL FATTORIALE #DI UN NUMERO def fattoriale(n): """Il fattoriale di un numero indica il prodotto di quel numero per tutti i suoi antecedenti""" if n == 1: return 1 else: return (n * fattoriale(n-1)) res = int(input("Inserisci un numero: ")) if res >= 1: print("Il fattoriale di", res, "è", fattoriale(res))
DEEPENING
In Python, a function is a block of code that can be reused to perform a specific task. “Function objects” refers to the fact that functions in Python are full-fledged objects and can be manipulated as such. Here are some key features of function objects in Python:
1. Definition of Functions:
Functions are defined using the def keyword followed by the function name and parentheses that may contain parameters.
def saluta(nome):
return f”Ciao, {nome}!”
2. Functions are First-Class Objects:
In Python, functions are treated as first-class objects, which means they can be assigned to variables, passed as arguments to other functions, and returned by other functions.
def saluta(nome):
return f”Ciao, {nome}!”
messaggio = saluta # Assegno la funzione a una variabile
print(messaggio(“Luca”)) # Chiamo la funzione tramite la variabile
3. Functions as Arguments:
Functions can be passed as arguments to other functions.
def applica_funzione(f, valore):
return f(valore)
def raddoppia(x):
return x * 2
risultato = applica_funzione(raddoppia, 5) # Passo la funzione raddoppia come argomento
print(risultato) # Stampa: 10
4. Returning Functions:
Functions can return other functions, allowing the creation of function factories.
def crea_moltiplicatore(m):
return lambda x: x * m
raddoppia = crea_moltiplicatore(2)
triplica = crea_moltiplicatore(3)
print(raddoppia(5)) # Stampa: 10
print(triplica(5)) # Stampa: 15
These are the basics of function objects in Python. Functions are extremely flexible and powerful, and understanding how they work as objects can help you write more modular and reusable code.
Leave A Comment