python funzioni moduli import

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 del main().
  • 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.