Funzioni Avanzate e Moduli in Python
Obiettivi della pillola
Questa pillola approfondisce le funzioni e la struttura del codice:
- capire come Python gestisce il passaggio dei parametri (mutabili vs immutabili);
- organizzare il codice in moduli riutilizzabili;
- utilizzare il costrutto
if __name__ == "__main__":.
Passaggio per Valore o Riferimento?
In Python, il passaggio dei parametri è tecnicamente definito “Passaggio per Assegnamento” (o Pass by Object Reference). Ciò che conta è se l’oggetto passato è mutabile o immutabile.
Oggetti Immutabili (int, str, tuple)
Se passi un numero o una stringa, la funzione lavora su una “copia locale” del riferimento. Modificarlo dentro la funzione non ha effetto sulla variabile esterna.
def prova_modifica(x):
x = 100 # Assegna un nuovo valore solo a 'x' locale
print(f"Dentro: {x}")
numero = 5
prova_modifica(numero)
print(f"Fuori: {numero}") # Stampa ancora 5!
Oggetti Mutabili (list, dict, set)
Se passi una lista, la funzione riceve il riferimento allo stesso oggetto in memoria. Se modifichi il contenuto (es. .append()), la modifica persiste anche fuori.
def aggiungi_elemento(lista):
lista.append("Nuovo") # Modifica l'oggetto esistente
mia_lista = ["A", "B"]
aggiungi_elemento(mia_lista)
print(mia_lista) # Stampa ['A', 'B', 'Nuovo']
Nota: Attenzione: se dentro la funzione fai
lista = [...], stai creando una nuova lista locale e perdi il legame con quella esterna (comportamento simile agli immutabili).
I Moduli in Python
Un modulo è semplicemente un file che termina con .py. Permette di dividere il codice in più file per tenerlo ordinato.
Immagina di avere un file matematica.py:
# File: matematica.py
PI_GRECO = 3.14
def area_cerchio(raggio):
return PI_GRECO * (raggio ** 2)
Puoi usare questo modulo in un altro script (main.py) con import:
# File: main.py
import matematica as mat # 'as' crea un alias
r = 5
print(mat.area_cerchio(r))
Il blocco if __name__ == "__main__":
Quando esegui un file Python, l’interprete assegna alla variabile speciale interna __name__ il valore "__main__". Se invece il file viene importato come modulo, __name__ sarà uguale al nome del file.
Questo controllo serve a creare script che possono funzionare sia come programmi autonomi sia come moduli importabili senza eseguire codice indesiderato.
Struttura ideale di uno script:
# Import librerie standard
import sys
import random
# Definizione funzioni
def calcola():
return random.randint(1, 100)
def main():
"""Funzione principale che coordina il programma."""
valore = calcola()
print(f"Il valore calcolato e: {valore}")
# Entry point
if __name__ == "__main__":
# Questo blocco viene eseguito SOLO se lanci questo file
# direttamente, NON se lo importi.
main()
Perché usare questa struttura?
- Ordine: Le importazioni sono in alto, le funzioni al centro, l’esecuzione in fondo.
- Riutilizzabilità: Puoi importare le funzioni
calcola()in un altro programma senza che parta automaticamente la stampa delmain(). - Scope: Usare una funzione
main()evita di creare variabili globali che potrebbero interferire tra loro.
In breve: Usa sempre il blocco __main__ nei tuoi script. Ricorda che le liste passate alle funzioni possono essere modificate permanentemente, mentre i numeri e le stringhe no.
EC