diff --git a/.github/workflows/generate-pdfs-on-release.yml b/.github/workflows/generate-pdfs-on-release.yml index 91bfa81..4056ffb 100644 --- a/.github/workflows/generate-pdfs-on-release.yml +++ b/.github/workflows/generate-pdfs-on-release.yml @@ -23,6 +23,7 @@ jobs: run: | sudo apt-get update sudo apt-get install -y pandoc texlive-xetex texlive-fonts-recommended texlive-plain-generic + sudo apt-get install -y poppler-utils pip install jupyter==1.1.1 nbconvert==7.16.6 - name: Convert notebooks to PDF @@ -38,6 +39,12 @@ jobs: echo "Converting $notebook to PDF..." jupyter nbconvert --to pdf "$notebook" --output-dir=pdfs || echo "Warning: Failed to convert $notebook" done + + # Merge all PDFs into one + echo "Merging PDFs..." + pdfunite pdfs/*.pdf corso-python-basic.pdf + find pdfs -type f -name "*.pdf" ! -name "corso-python-basic.pdf" -delete + echo "✅ Conversion complete! Final merged file: corso-python-basic.pdf" - name: Upload PDFs to release env: diff --git a/00_sommario_corso.ipynb b/00_sommario_corso.ipynb index 5b4962d..2c00c23 100755 --- a/00_sommario_corso.ipynb +++ b/00_sommario_corso.ipynb @@ -7,7 +7,7 @@ "source": [ "# 📚 Sommario del Corso Python per Principianti\n", "\n", - "Questo corso è un percorso introduttivo pensato per aiutarti a muovere i primi passi nel linguaggio Python. È uno dei pochi corsi per principianti di questo tipo disponibili interamente in italiano, progettato per offrirti un apprendimento chiaro e accessibile.\n", + "Questo corso è un percorso introduttivo pensato per imparare a muovere i primi passi nel linguaggio Python. È uno dei pochi corsi per principianti di questo tipo disponibili interamente in italiano, progettato per offrire un apprendimento chiaro e accessibile.\n", "\n", "---\n", "## 🧠 Python nell'Era dell'Intelligenza Artificiale\n", diff --git a/01_primi_passi.ipynb b/01_primi_passi.ipynb index a05e80d..fd4de08 100755 --- a/01_primi_passi.ipynb +++ b/01_primi_passi.ipynb @@ -7,7 +7,7 @@ "source": [ "# 🐍 Primi passi con Python\n", "\n", - "In questa lezione, vedremo cosa ti serve per iniziare, dalle competenze di base agli strumenti per scrivere i primi programmi.\n", + "In questa lezione, vedremo cosa serve per iniziare, partendo dalle competenze di base agli strumenti per scrivere i primi programmi.\n", "\n", "---" ] @@ -17,7 +17,7 @@ "id": "038c35b4", "metadata": {}, "source": [ - "## 1. Pre-requisiti e strumenti necessari 🛠️\n", + "## Pre-requisiti e strumenti necessari 🛠️\n", "\n", "### Competenze richieste\n", "\n", @@ -33,12 +33,12 @@ "source": [ "### L'ambiente di sviluppo: Editor o IDE?\n", "\n", - "Per scrivere codice, hai bisogno di un programma chiamato **editor di testo** o di un **IDE (Integrated Development Environment)**.\n", + "Per scrivere codice, occorre un programma chiamato **editor di testo** o di un **IDE (Integrated Development Environment)**.\n", "\n", - "- **Editor di testo:** Un programma leggero (come vi su Linux/macOS o Blocco Note su Windows) che ti permette di scrivere testo semplice. È perfetto per iniziare.\n", + "- **Editor di testo:** Un programma leggero (come **vi** su Linux/macOS o **Blocco Note** su Windows) che permette di scrivere testo semplice. È perfetto per iniziare.\n", "- **IDE:** Un ambiente più completo che include un editor, un debugger, un compilatore e altri strumenti. È ottimo per progetti complessi, ma può essere più impegnativo per i principianti.\n", "\n", - "Per questo corso, un **editor di testo** è più che sufficiente. Se vuoi utilizzare un IDE, ti consigliamo **[Visual Studio Code (VS Code)](https://code.visualstudio.com/)**, che è gratuito, leggero e disponibile per tutti i sistemi operativi, nel caso di utilizzo di un IDE." + "Per questo corso, un **editor di testo** è più che sufficiente. Se si vuole utilizzare un IDE, consigliamo **[Visual Studio Code (VS Code)](https://code.visualstudio.com/)**, che è gratuito, leggero e disponibile per tutti i sistemi operativi, nel caso di utilizzo di un IDE." ] }, { @@ -48,19 +48,19 @@ "source": [ "### Installazione di Python e dell'editor\n", "\n", - "A seconda del tuo sistema operativo, i passaggi sono leggermente diversi. Assicurati di avere Python installato e configurato correttamente prima di procedere.\n", + "A seconda del sistema operativo in uso, i passaggi sono leggermente diversi. Prima di iniziare a programmare occorre assicurasi di avere Python installato e configurato correttamente prima di procedere.\n", "\n", "**Su Linux**\n", - "- **Python:** È quasi sempre preinstallato. Verifica con `python3 --version`.\n", - "- **Editor:** Installa **VS Code** dal sito ufficiale o tramite il gestore di pacchetti (ad es., `sudo snap install code --classic`).\n", + "- **Python:** È quasi sempre preinstallato. Si può verificare con il comando `python3 --version`.\n", + "- **Editor:** [Opzionale] Si può installare **VS Code** dal sito ufficiale o tramite il gestore di pacchetti (ad es., `sudo snap install code --classic`).\n", "\n", "**Su macOS**\n", - "- **Python:** Scarica l'installer dal **[sito ufficiale di Python](https://www.python.org/downloads/)** o usa Homebrew (`brew install python3`).\n", - "- **Editor:** Installa **[VS Code](https://code.visualstudio.com/)** dal sito ufficiale.\n", + "- **Python:** Scaricare l'installer dal **[sito ufficiale di Python](https://www.python.org/downloads/)** o usa Homebrew (`brew install python3`).\n", + "- **Editor:** [Opzionale] Si può installare **[VS Code](https://code.visualstudio.com/)** dal sito ufficiale.\n", "\n", "**Su Windows**\n", - "- **Python:** Scarica l'installer dal **[sito ufficiale di Python](https://www.python.org/downloads/)**. **Ricorda di spuntare la casella `Add Python to PATH`** durante l'installazione.\n", - "- **Editor:** Installa **[VS Code](https://code.visualstudio.com/)** dal sito ufficiale." + "- **Python:** Scaricare l'installer dal **[sito ufficiale di Python](https://www.python.org/downloads/)**. **Ricorda di spuntare la casella `Add Python to PATH`** durante l'installazione.\n", + "- **Editor:** [Opzionale] Si può installare **[VS Code](https://code.visualstudio.com/)** dal sito ufficiale." ] }, { @@ -69,9 +69,12 @@ "metadata": {}, "source": [ "---\n", - "## 2. Il tuo primo programma: \"Hello, World!\"\n", + "## Il primo programma: \"Hello, World!\"\n", "\n", - "Ora che hai tutto il necessario, possiamo scrivere il nostro primo programma. In Python, stampare il messaggio \"Hello, World!\" è possibile grazie alla funzione `print()`." + "Ora che si ha disposizione tutto il necessario, si può scrivere il primo programma. In Python, stampare il classico messaggio \"Hello, World!\" è possibile grazie alla funzione `print()`.\n", + "\n", + "### Una breve nota storica\n", + "La tradizione di usare *\"Hello, World!\"* come primo programma risale al linguaggio C. È apparsa per la prima volta nel 1972, nel libro **\"The C Programming Language\"** di Brian Kernighan e Dennis Ritchie, i creatori del linguaggio. In realtà, una versione preliminare di questo esempio comparve già in un documento di Kernighan del 1974, intitolato *\"Programming in C: A Tutorial\"*. Da allora, è diventato un vero e proprio **rito di iniziazione** per chi inizia a programmare: un modo semplice e immediato per verificare che tutto funzioni correttamente (ambiente di sviluppo, compilatore o interprete) e per avere la soddisfazione di vedere un codice funzionare in un nuovo linguaggio per la prima volta." ] }, { @@ -91,8 +94,8 @@ "source": [ "**Perché è così importante?** Questo semplice comando ci dimostra tre cose fondamentali:\n", "- **Sintassi chiara:** La sintassi di Python è intuitiva e facile da leggere.\n", - "- **Funzioni:** Hai già usato la tua prima funzione (`print()`). Le funzioni sono blocchi di codice riutilizzabili.\n", - "- **Esecuzione:** Hai eseguito un programma completo, anche se composto da una sola riga." + "- **Funzioni:** E' stata usata una funzione (`print()`). Le funzioni sono blocchi di codice riutilizzabili.\n", + "- **Esecuzione:** E' stato eseguito un programma completo, anche se composto da una sola riga." ] }, { @@ -101,9 +104,9 @@ "metadata": {}, "source": [ "---\n", - "## 3. Come eseguire uno script Python\n", + "## Come eseguire uno script Python\n", "\n", - "Per eseguire un programma più strutturato, lo salveremo in un file con estensione `.py` e lo eseguiremo da riga di comando (il terminale)." + "Per eseguire un programma più strutturato, salveremo il codice in un file con estensione `.py` e lo eseguiremo da riga di comando (il terminale)." ] }, { @@ -113,7 +116,7 @@ "source": [ "### Interazione con l'utente: la funzione `input()` 💬\n", "\n", - "Mentre `print()` ti permette di mostrare un output, la funzione **`input()`** ti consente di chiedere all'utente di inserire dei dati. Quando Python incontra `input()`, il programma si ferma e attende che l'utente scriva qualcosa e prema Invio. Il testo che l'utente inserisce viene restituito come una stringa. Spiegheremo in dettaglio come funziona `input()` più avanti nel corso, ma per ora puoi vederla in azione nel prossimo esempio." + "Mentre `print()` permette di mostrare un output, la funzione **`input()`** consente di chiedere all'utente di inserire dei dati. Quando Python incontra `input()`, il programma si ferma e attende che l'utente scriva qualcosa e prema Invio. Il testo che l'utente inserisce viene restituito come una stringa. Spiegheremo in dettaglio come funziona `input()` più avanti nel corso, qui si può vederla in azione nel prossimo esempio." ] }, { @@ -122,7 +125,7 @@ "metadata": {}, "source": [ "### Esempio: `greet.py`\n", - "Crea un file di testo e salvalo come `greet.py` nella tua cartella di lavoro. Al suo interno, scrivi il seguente codice:" + "Creare un file di testo e salvalo come `greet.py` in una cartella di lavoro. Al suo interno, scrivere il seguente codice:" ] }, { @@ -147,12 +150,12 @@ "source": [ "### Il costrutto `if __name__ == \"__main__\":` 🤔\n", "\n", - "Hai sicuramento notato il blocco `if __name__ == \"__main__\":`. Questo è un costrutto comune e importante in Python. Serve a controllare se il file Python viene eseguito direttamente o se viene importato come modulo in un altro script.\n", + "Il primo blocco che viene all'attenzione è il blocco `if __name__ == \"__main__\":`. Questo è un costrutto comune e importante in Python. Serve a controllare se il file Python viene eseguito direttamente o se viene importato come modulo in un altro script.\n", "\n", "Analizziamo il metodo più in dettaglio:\n", "1. **`__name__`** è una variabile speciale che Python imposta automaticamente.\n", - "2. Quando esegui il file direttamente (ad es. con `python3 saluto.py`), il valore di `__name__` è `\"__main__\"`.\n", - "3. Se un altro file Python importa il tuo `saluto.py` (`import saluto`), il valore di `__name__` sarà il nome del modulo, cioè `\"saluto\"`.\n", + "2. Quando viene eseguito il file direttamente (ad es. con `python3 saluto.py`), il valore di `__name__` è `\"__main__\"`.\n", + "3. Se un altro file Python importa il file `saluto.py` (`import saluto`), il valore di `__name__` sarà il nome del modulo, cioè `\"saluto\"`.\n", "\n", "Di conseguenza, il codice all'interno del blocco `if` verrà eseguito **solo se il file viene lanciato come programma principale**, e non quando viene importato da un altro file." ] @@ -164,12 +167,12 @@ "source": [ "### Passare argomenti esterni al programma 🚀\n", "\n", - "Spesso, invece di chiedere all'utente di inserire dati con `input()`, vuoi che il programma li riceva direttamente quando lo lanci da terminale. Puoi farlo usando il modulo della libreria standard `sys` e in particolare la lista `sys.argv`.\n", + "Spesso, invece di chiedere all'utente di inserire dati con `input()`, si vuole che il programma li riceva direttamente quando viene eseguito da terminale. Questo è possibile farlo usando il modulo della libreria standard `sys` e in particolare la lista `sys.argv`.\n", "\n", "**`sys.argv`** (argument vector) è una lista che contiene tutti gli argomenti passati dalla riga di comando. Il primo elemento, `sys.argv[0]`, è sempre il nome del file script stesso.\n", "\n", "### Esempio: `saluta_args.py`\n", - "Crea un nuovo file chiamato `saluta_args.py` con il seguente codice. Questo programma saluterà una persona il cui nome è fornito come argomento esterno.\n", + "Creare un nuovo file chiamato `saluta_args.py` con il seguente codice. Questo programma saluterà una persona il cui nome è fornito come argomento esterno.\n", "\n" ] }, @@ -199,9 +202,9 @@ "metadata": {}, "source": [ "---\n", - "## 4. Importare moduli e librerie\n", + "## Importare moduli e librerie\n", "\n", - "Python ha una ricca **libreria standard** di moduli che puoi importare per estendere le funzionalità del tuo codice. Le librerie sono collezioni di funzioni e strumenti predefiniti.\n", + "Python ha una ricca **libreria standard** di moduli che si può importare per estendere le funzionalità all'interno di un codice. Le librerie sono collezioni di funzioni e strumenti predefiniti.\n", "\n", "### Come e dove Python cerca i moduli 🗺️\n", "\n", @@ -236,16 +239,16 @@ "metadata": {}, "source": [ "---\n", - "## 5. Un breve sguardo all'interprete\n", + "## Un breve sguardo all'interprete\n", "\n", - "Python è un **linguaggio interpretato**, a differenza di linguaggi come C o C++ che sono compilati. Questo significa che il tuo codice non viene tradotto in un file eseguibile separato prima di essere lanciato.\n", + "Python è un **linguaggio interpretato**, a differenza di linguaggi come C o C++ che sono compilati. Questo significa che il codice non viene tradotto in un file eseguibile separato prima di essere lanciato.\n", "\n", "Il processo di esecuzione funziona in questo modo:\n", "\n", "1. **Lettura del codice sorgente**: L'interprete Python legge il tuo file `.py` riga per riga.\n", - "2. **Conversione in bytecode**: Il codice sorgente viene convertito in un codice intermedio, chiamato **bytecode**. Questo bytecode è una rappresentazione a basso livello del tuo codice, ma non è ancora eseguibile direttamente dal sistema operativo.\n", + "2. **Conversione in bytecode**: Il codice sorgente viene convertito in un codice intermedio, chiamato **bytecode**. Questo bytecode è una rappresentazione a basso livello del codice, ma non è ancora eseguibile direttamente dal sistema operativo.\n", "3. **Esecuzione da parte della PVM**: La **Python Virtual Machine (PVM)** esegue il bytecode. La PVM è un programma che fa da ponte tra il tuo codice e il sistema operativo. Questa architettura rende Python estremamente **portabile**; lo stesso bytecode può essere eseguito su diverse piattaforme, a patto che sia presente l'interprete Python.\n", - "4. **File `.pyc`**: Per ottimizzare il processo, Python salva il bytecode in file con estensione `.pyc` (Python compiled). Quando esegui un programma una seconda volta, Python controlla se il file `.pyc` è più recente del file `.py` originale. Se è così, salta la fase di conversione e esegue direttamente il bytecode, velocizzando l'avvio.\n", + "4. **File `.pyc`**: Per ottimizzare il processo, Python salva il bytecode in file con estensione `.pyc` (Python compiled). Quando viene eseguito un programma una seconda volta, Python controlla se il file `.pyc` è più recente del file `.py` originale. Se è così, salta la fase di conversione e esegue direttamente il bytecode, velocizzando l'avvio.\n", "\n", "Questo processo automatico e flessibile è uno dei motivi principali per cui lo sviluppo con Python è così rapido ed efficiente." ] @@ -256,7 +259,7 @@ "metadata": {}, "source": [ "---\n", - "## 6. Eseguire codice con Jupyter Notebook\n", + "## Eseguire codice con Jupyter Notebook\n", "\n", "---" ] @@ -266,7 +269,7 @@ "id": "jupyter_section_1", "metadata": {}, "source": [ - "### 6.1. Cos'è Jupyter Notebook?\n", + "### Cos'è Jupyter Notebook?\n", "\n", "Jupyter Notebook è un'applicazione web open-source che ti permette di creare e condividere documenti contenenti codice live, equazioni, visualizzazioni e testo esplicativo. È uno strumento essenziale per la **data science**, l'apprendimento automatico e la ricerca scientifica, ma è anche ideale per la didattica, poiché ti permette di eseguire piccoli blocchi di codice e vederne immediatamente i risultati." ] @@ -276,9 +279,9 @@ "id": "jupyter_section_2", "metadata": {}, "source": [ - "### 6.2. L'interfaccia di Jupyter\n", + "### L'interfaccia di Jupyter\n", "\n", - "Una volta avviato, vedrai la dashboard di Jupyter. Da qui puoi navigare tra le cartelle e creare nuovi notebook. Un notebook è composto da **celle**.\n", + "Una volta avviato, si vedrà la dashboard di Jupyter. Da qui si può navigare tra le cartelle e creare nuovi notebook. Un notebook è composto da **celle**.\n", "\n", "1. **Celle di Codice**: per scrivere ed eseguire codice Python.\n", "2. **Celle Markdown**: per scrivere testo formattato, titoli e commenti." @@ -289,9 +292,9 @@ "id": "jupyter_section_3", "metadata": {}, "source": [ - "### 6.3. Eseguire una cella di codice\n", + "### Eseguire una cella di codice\n", "\n", - "Per eseguire una cella, selezionala e premi **`Shift + Invio`**. Vedrai l'output apparire subito sotto la cella. Il numero tra parentesi `[ ]` indica l'ordine di esecuzione." + "Per eseguire una cella, selezionarla e premere **`Shift + Invio`**. Si vedrà l'output apparire subito sotto la cella. Il numero tra parentesi `[ ]` indica l'ordine di esecuzione." ] }, { @@ -315,7 +318,7 @@ "source": [ "#### Assegnare e usare variabili\n", "\n", - "Puoi assegnare valori a variabili e usarle in altre celle. Le variabili restano in memoria finché il kernel non viene riavviato." + "Si possono assegnare valori a variabili e usarle in altre celle. Le variabili restano in memoria finché il kernel non viene riavviato." ] }, { @@ -344,7 +347,7 @@ "id": "jupyter_section_4", "metadata": {}, "source": [ - "### 6.4. L'Output delle celle\n", + "### L'Output delle celle\n", "\n", "Jupyter mostra automaticamente il valore dell'ultima riga di codice, anche senza `print()`." ] @@ -365,7 +368,7 @@ "id": "jupyter_section_4_sub", "metadata": {}, "source": [ - "Se vuoi visualizzare più valori, devi usare `print()`." + "Se si vogliono visualizzare più valori, occorre usare `print()`." ] }, { @@ -387,9 +390,9 @@ "id": "jupyter_section_5", "metadata": {}, "source": [ - "### 6.5. Errori e Debugging\n", + "### Errori e Debugging\n", "\n", - "Jupyter ti aiuta a capire gli errori stampando l'intera traccia dell'errore (traceback)." + "Jupyter aiuta a capire gli errori stampando l'intera traccia dell'errore (traceback)." ] }, { @@ -420,7 +423,7 @@ "metadata": {}, "source": [ "### Esercizio 1: Saluto personalizzato\n", - "Modifica il file `greet.py` per chiedere il nome e stampare un messaggio di benvenuto più elaborato." + "Modificare il file `greet.py` per chiedere il nome e stampare un messaggio di benvenuto più elaborato." ] }, { @@ -437,7 +440,7 @@ "metadata": {}, "source": [ "### Esercizio 2: Usare un modulo\n", - "Scrivi un nuovo script chiamato `calculate_square_root.py` che usa la libreria `math` per chiedere un numero all'utente e stampare la sua radice quadrata." + "Scrivere un nuovo script chiamato `calculate_square_root.py` che usa la libreria `math` per chiedere un numero all'utente e stampare la sua radice quadrata." ] }, { diff --git a/02_sintassi_base.ipynb b/02_sintassi_base.ipynb index c466fcd..20172ce 100755 --- a/02_sintassi_base.ipynb +++ b/02_sintassi_base.ipynb @@ -8,7 +8,7 @@ "# ⌨️ Sintassi base di Python\n", "\n", "---\n", - "Dopo aver configurato il tuo ambiente e aver scritto il tuo primo programma, è il momento di esplorare la grammatica di base del linguaggio. In questa lezione, vedremo la sintassi fondamentale di Python: come si scrivono i commenti, l'importanza dell'indentazione, le variabili, i tipi di dati più comuni, le strutture di controllo del flusso e i cicli. Questi sono i concetti essenziali che userai in ogni programma." + "Dopo aver configurato l'ambiente di lavoro e aver scritto il primo programma, è il momento di esplorare la grammatica di base del linguaggio. In questa lezione, vedremo la sintassi fondamentale di Python: come si scrivono i commenti, l'importanza dell'indentazione, le variabili, i tipi di dati più comuni, le strutture di controllo del flusso e i cicli. Questi sono i concetti essenziali che si useranno in ogni programma." ] }, { @@ -16,7 +16,7 @@ "id": "d00ff8aa", "metadata": {}, "source": [ - "## 1. Commenti\n", + "## Commenti\n", "I commenti sono righe di testo nel codice che vengono ignorate dall'interprete Python. Servono per spiegare cosa fa una determinata parte del codice, renderlo più leggibile e documentarlo. Sono uno strumento essenziale per una buona programmazione.\n", "\n", "### Commento su singola riga\n", @@ -61,17 +61,17 @@ "metadata": {}, "source": [ "---\n", - "## 2. Indentazione: Perché è così importante? 🤔\n", + "## Indentazione: Perché è così importante? 🤔\n", "\n", "L'**indentazione** è uno dei concetti più importanti e unici della sintassi di Python. A differenza di molti altri linguaggi (come Java o C++) che usano parentesi graffe `{}` per definire blocchi di codice, Python usa lo spazio bianco. Ogni blocco di codice, come quello all'interno di un'istruzione `if` o di un ciclo `for`, deve essere indentato con la stessa quantità di spazi.\n", "\n", "### Perché Python usa l'indentazione?\n", - "A prima vista può sembrare una scelta strana, ma ci sono ottime ragioni dietro. I creatori di Python hanno voluto **forzare gli sviluppatori a scrivere codice più pulito e leggibile**. In altri linguaggi, l'indentazione è una convenzione di stile (puoi scrivere tutto su una riga se vuoi), ma in Python è una regola sintattica. Questo ha due vantaggi principali:\n", + "I creatori di Python hanno voluto **forzare gli sviluppatori a scrivere codice più pulito e leggibile**. In altri linguaggi, l'indentazione è una convenzione di stile (si può scrivere tutto su una riga se vuoi), ma in Python è una regola sintattica. Questo ha due vantaggi principali:\n", "\n", "1. **Maggiore leggibilità:** Il codice indentato è più facile da leggere e da seguire visivamente. Quando tutti i programmatori seguono la stessa regola, la manutenzione del codice diventa molto più semplice, specialmente in team di sviluppo.\n", "2. **Meno errori:** Non c'è ambiguità. Un blocco di codice inizia con un'indentazione maggiore e finisce quando l'indentazione torna al livello precedente. Non ci sono parentesi graffe da dimenticare, il che elimina una fonte comune di bug.\n", "\n", - "La convenzione (consigliata dallo standard PEP 8) è usare **4 spazi** per ogni livello di indentazione. Non mescolare spazi e tabulazioni per evitare errori, i moderni editor di testo lo gestiscono in automatico." + "La convenzione (consigliata dallo standard PEP 8) è usare **4 spazi** per ogni livello di indentazione. Non bisogna mescolare spazi e tabulazioni per evitare errori, i moderni editor di testo lo gestiscono in automatico." ] }, { @@ -114,9 +114,9 @@ "metadata": {}, "source": [ "---\n", - "## 3. Variabili e assegnazioni\n", + "## Variabili e assegnazioni\n", "\n", - "Una **variabile** è un contenitore a cui assegni un valore. In Python, non è necessario dichiarare il tipo di una variabile in anticipo; l’interprete lo deduce automaticamente dal valore che le assegni. Questo approccio si chiama **tipizzazione dinamica** ed è stato scelto per rendere il linguaggio più **semplice e veloce da scrivere**, soprattutto per chi inizia o per chi sviluppa prototipi. Non dover specificare il tipo riduce la quantità di codice “boilerplate” e permette di concentrarsi sulla logica.\n", + "Una **variabile** è un contenitore a si assegna un valore. In Python, non è necessario dichiarare il tipo di una variabile in anticipo; l’interprete lo deduce automaticamente dal valore che le viene assegnato. Questo approccio si chiama **tipizzazione dinamica** ed è stato scelto per rendere il linguaggio più **semplice e veloce da scrivere**, soprattutto per chi inizia o per chi sviluppa prototipi. Non dover specificare il tipo riduce la quantità di codice “boilerplate” e permette di concentrarsi sulla logica.\n", "\n", "I nomi delle variabili devono iniziare con una lettera o un underscore (`_`) e possono contenere lettere, numeri e underscore. Inoltre, sono **case-sensitive**: ad esempio `variabile`, `Variabile` e `VARIABILE` sono considerati tre identificatori distinti.\n", "\n", @@ -151,9 +151,9 @@ "metadata": {}, "source": [ "---\n", - "## 4. Tipi di dati\n", + "## Tipi di dati\n", "\n", - "Ogni informazione che manipoliamo in Python ha un tipo. I tipi di dati più comuni sono:\n", + "Ogni informazione che viene manipolata in Python ha un tipo. I tipi di dati più comuni sono:\n", "\n", "| Tipo | Descrizione | Esempio |\n", "|-----------|--------------------------------------------|-----------------------|\n", @@ -166,7 +166,7 @@ "| `dict` | Collezione non ordinata di coppie chiave-valore | `{'nome': 'Anna', 'età': 30}` |\n", "| `set` | Collezione non ordinata di elementi unici | `{1, 2, 3}` |\n", "\n", - "Per conoscere il tipo di un dato o di una variabile, puoi usare la funzione `type()`." + "Per conoscere il tipo di un dato o di una variabile, si può usare la funzione `type()`." ] }, { @@ -203,7 +203,7 @@ "### Tipi di dato complessi\n", "\n", "- **List (`list`)**: Una lista è una collezione di elementi **ordinata** e **modificabile**. È la struttura dati più versatile per memorizzare insiemi di dati che possono cambiare.\n", - "- **Tuple (`tuple`)**: Simile a una lista, ma una tupla è **immutabile**, il che significa che non puoi aggiungere, rimuovere o modificare i suoi elementi dopo la creazione. Questo la rende più efficiente in alcuni casi e ideale per dati che non devono cambiare.\n", + "- **Tuple (`tuple`)**: Simile a una lista, ma una tupla è **immutabile**, il che significa che non si possono aggiungere, rimuovere o modificare i suoi elementi dopo la creazione. Questo la rende più efficiente in alcuni casi e ideale per dati che non devono cambiare.\n", "- **Dictionary (`dict`)**: Un dizionario è una collezione di dati non ordinata che memorizza le informazioni come coppie di **chiave-valore**. È perfetta per associare un valore a una chiave specifica, come un nome a un'età o un codice a un prodotto.\n", "- **Set (`set`)**: Un set è una collezione di elementi non ordinata e **senza duplicati**. Viene usata per testare rapidamente l'appartenenza di un elemento o per eliminare i duplicati da una collezione." ] @@ -242,7 +242,7 @@ "source": [ "---\n", "### Conversione di tipo (casting)\n", - "Puoi convertire un tipo in un altro usando funzioni come `int()`, `float()`, `str()`, `bool()`. Questo è spesso necessario, ad esempio, per convertire l'input di un utente da stringa a numero." + "E' possibile convertire un tipo in un altro usando funzioni come `int()`, `float()`, `str()`, `bool()`. Questo è spesso necessario, ad esempio, per convertire l'input di un utente da stringa a numero." ] }, { @@ -269,7 +269,7 @@ "metadata": {}, "source": [ "---\n", - "## 5. Operatori aritmetici\n", + "## Operatori aritmetici\n", "\n", "Python supporta le classiche operazioni matematiche sui numeri.\n", "\n", @@ -303,7 +303,7 @@ "metadata": {}, "source": [ "---\n", - "## 6. Operatori di confronto e logici\n", + "## Operatori di confronto e logici\n", "\n", "Gli operatori di confronto e logici sono usati per prendere decisioni nel codice. Le loro espressioni restituiscono sempre un valore booleano (`True` o `False`).\n", "\n", @@ -365,9 +365,9 @@ "metadata": {}, "source": [ "---\n", - "## 7. Controllo del flusso: `if`, `elif`, `else`\n", + "## Controllo del flusso: `if`, `elif`, `else`\n", "\n", - "Il **controllo del flusso** ti permette di eseguire blocchi di codice in base a una condizione. Si usano le parole chiave `if`, `elif` (else if), e `else`.\n", + "Il **controllo del flusso** permette di eseguire blocchi di codice in base a una condizione. Si usano le parole chiave `if`, `elif` (else if), e `else`.\n", "\n", "Sintassi di base:\n", "```python\n", @@ -377,8 +377,7 @@ " # code block se condition1 is False but condition2 is True\n", "else:\n", " # code block if none of the previous conditions are true\n", - "```\n", - "Remember that indentation is essential to define code blocks!!" + "```\n" ] }, { @@ -403,7 +402,7 @@ "metadata": {}, "source": [ "---\n", - "## 8. Cicli: `for` e `while`\n", + "## Cicli: `for` e `while`\n", "\n", "I cicli servono a ripetere un blocco di codice più volte.\n", "\n", @@ -451,7 +450,7 @@ "metadata": {}, "source": [ "---\n", - "## 9. Funzioni base: definizione e chiamata\n", + "## Funzioni base: definizione e chiamata\n", "\n", "Una **funzione** è un blocco di codice riutilizzabile che esegue un compito specifico. Le funzioni rendono il codice organizzato, modulare e più facile da gestire. Si definiscono con la parola chiave `def`.\n", "\n", @@ -461,7 +460,7 @@ " # The code inside here runs only when the function is called\n", " print(f\"Hello, {user_name}!\")\n", "```\n", - "Dopo la definizione, la funzione non esegue il codice. Devi **chiamarla** per attivarla." + "Dopo la definizione, la funzione non esegue il codice, occorre **chiamarla** per attivarla." ] }, { @@ -483,7 +482,7 @@ "metadata": {}, "source": [ "---\n", - "## 10. Funzioni di input e output\n", + "## Funzioni di input e output\n", "\n", "### Funzione `print()`\n", "La funzione `print()` serve per visualizzare l'output a schermo. È estremamente versatile e supporta la formattazione avanzata con le **f-string** (`f-string`), un modo potente per incorporare variabili all'interno di una stringa in modo leggibile e conciso.\n", @@ -519,26 +518,26 @@ "## Esercizi\n", "\n", "### Esercizio 1: Variabili e tipi\n", - "- Crea una variabile `user_name` e assegnale il tuo nome come stringa.\n", - "- Crea una variabile `age` con la tua età come intero.\n", - "- Stampa una frase del tipo: \"Hello, my name is and I am years old.\"\n", + "- Creare una variabile `user_name` e assegnarle il proprio nome come stringa.\n", + "- Creare una variabile `age` con la propria età come intero.\n", + "- Stampare una frase del tipo: \"Hello, my name is and I am years old.\"\n", "\n", "### Esercizio 2: Operatori e confronto\n", - "- Scrivi un programma che chiede due numeri all’utente.\n", - "- Stampa se il primo numero è maggiore, minore o uguale al secondo.\n", + "- Scrivere un programma che chiede due numeri all’utente.\n", + "- Stampare se il primo numero è maggiore, minore o uguale al secondo.\n", "\n", "### Esercizio 3: Controllo del flusso\n", - "- Scrivi un programma che chiede un voto (0-100).\n", + "- Scrivere un programma che chiede un voto (0-100).\n", "- Se il voto è maggiore o uguale a 60, stampa “Passed”.\n", "- Se il voto è tra 40 e 59, stampa “Remedial”.\n", "- Altrimenti stampa “Failed”.\n", "\n", "### Esercizio 4: Ciclo for\n", - "- Stampa i numeri da 1 a 10 usando un ciclo `for`.\n", + "- Stampare i numeri da 1 a 10 usando un ciclo `for`.\n", "\n", "### Esercizio 5: Ciclo while\n", - "- Chiedi all’utente di indovinare un numero segreto (ad esempio 7).\n", - "- Continua a chiedere finché non indovina." + "- Chiedere all’utente di indovinare un numero segreto (ad esempio 7).\n", + "- Continuare a chiedere finché non indovina." ] }, { diff --git a/03_strutture_dati.ipynb b/03_strutture_dati.ipynb index c05015f..627a476 100755 --- a/03_strutture_dati.ipynb +++ b/03_strutture_dati.ipynb @@ -22,79 +22,21 @@ "\n", "Scegliere la struttura dati giusta è cruciale per scrivere codice efficiente e pulito. Ad esempio:\n", "\n", - "- Hai una lista della spesa? Ti serve un contenitore in cui l'ordine è importante e puoi aggiungere/togliere elementi. In Python, useresti una **lista**.\n", - "- Vuoi memorizzare le coordinate fisse di un punto? Ti serve un contenitore che non può essere modificato. In Python, useresti una **tupla**.\n", - "- Vuoi salvare i contatti di una rubrica? Ti serve un contenitore che associ un nome a un numero di telefono. In Python, useresti un **dizionario**.\n", + "- Immaginiamo di avere una lista della spesa. E' opportuno avere una struttura in cui l'ordine è importante e si possono aggiungere/togliere elementi. In Python, per questo tipo di stritture si usa una **lista**.\n", + "- Immaginiamo di voler memorizzare le coordinate fisse di un punto. Quello che serve è una struttura i cui elementi non possono essere modificati. In Python, si usa una una **tupla**.\n", + "- Immaginiamo di voler salvare i contatti di una rubrica? Serve una struttura che associ un nome a un numero di telefono. In Python, si usa un **dizionario**.\n", "\n", "Nelle prossime sezioni, vedremo le caratteristiche di ogni struttura dati e i loro principali utilizzi." ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "---", - "\n", - "## Come accedere agli elementi (Indicizzazione, Chiavi e Slicing) 🎯\n", - "\n", - "Per accedere a un singolo elemento in una struttura dati si usano le **parentesi quadre `[]`**.\n", - "\n", - "- Per **Liste** e **Tuple**, si usa un **indice numerico**. L'indice parte da **0**. Indici negativi contano dalla fine (-1 è l'ultimo elemento).\n", - "```python\n", - "list_numbers = [10, 20, 30, 40, 50]\n", - "print(list_numbers[0]) # first element: 10\n", - "print(list_numbers[-1]) # last element: 50\n", - "```\n", - "- Per i **Dizionari**, si accede tramite la **chiave** associata al valore.\n", - "```python\n", - "user_data = {'name': 'Mario', 'age': 25}\n", - "print(user_data['name']) # Mario\n", - "```\n", - "- Per i **Set**, l'accesso diretto tramite `[]` non è possibile. Si può solo controllare se un elemento è presente con `in`.", - "\n", - "### Slicing: prendere più elementi in una volta\n", - "\n", - "Lo **slicing** permette di estrarre una parte di una sequenza (lista, tupla, stringa) senza modificare l'originale.\n", - "\n", - "Sintassi:\n", - "```python\n", - "sequence[start:stop:step]\n", - "```\n", - "- `start`: indice da cui iniziare (incluso), default = 0\n", - "- `stop`: indice dove fermarsi (escluso), default = fine sequenza\n", - "- `step`: quanti elementi saltare, default = 1\n", - "\n", - "Esempi:\n", - "```python\n", - "numbers = [10, 20, 30, 40, 50, 60]\n", - "\n", - "# From the third element to the end\n", - "print(numbers[2:]) # [30, 40, 50, 60]\n", - "\n", - "# From the second to the fourth element (fourth not included)\n", - "print(numbers[1:4]) # [20, 30, 40]\n", - "\n", - "# Get every two elements\n", - "print(numbers[::2]) # [10, 30, 50]\n", - "\n", - "# Reverse the list\n", - "print(numbers[::-1]) # [60, 50, 40, 30, 20, 10]\n", - "\n", - "# Using negative indices\n", - "print(numbers[-4:-1]) # [30, 40, 50]\n", - "```\n", - "\n" - ] -} -, { "cell_type": "markdown", "id": "ff5c0148", "metadata": {}, "source": [ - "## 1. Liste `[]`\n", + "## Liste `[]`\n", "\n", - "Le liste sono sequenze ordinate e **mutabili** di elementi. Questo significa che puoi modificarle dopo la creazione: aggiungere, rimuovere o cambiare elementi." + "Le liste sono sequenze ordinate e **mutabili** di elementi. Questo significa che si possono modificarle dopo la creazione e quindi aggiungere, rimuovere o cambiare elementi." ] }, { @@ -177,9 +119,9 @@ "id": "73c5a43b", "metadata": {}, "source": [ - "## 2. Tuple `()`\n", + "## Tuple `()`\n", "\n", - "Le tuple sono simili alle liste, ma sono **immutabili**. Una volta creata una tupla, non puoi aggiungere, rimuovere o modificare i suoi elementi. Sono più veloci e sicure, usate spesso per dati che non devono cambiare." + "Le tuple sono simili alle liste, ma sono **immutabili**. Una volta creata una tupla, non si possono aggiungere, rimuovere o modificare i suoi elementi. Sono più veloci e sicure, usate spesso per dati che non devono cambiare." ] }, { @@ -228,7 +170,7 @@ "id": "4ca75b23", "metadata": {}, "source": [ - "## 3. Set (Insiemi) `{}`\n", + "## Set (Insiemi) `{}`\n", "\n", "Un set è una collezione di elementi **non ordinata** e che **non permette duplicati**. È molto efficiente per verificare se un elemento è presente in una collezione e per eseguire operazioni matematiche sugli insiemi (unione, intersezione, differenza)." ] @@ -289,7 +231,7 @@ "id": "82c703f1", "metadata": {}, "source": [ - "## 4. Dizionari `{}`\n", + "## Dizionari `{}`\n", "\n", "I dizionari memorizzano dati come coppie **chiave-valore**. Ogni chiave deve essere unica e immutabile (come una stringa o un numero). Sono ideali per rappresentare dati strutturati e per un accesso diretto tramite la chiave." ] @@ -337,14 +279,64 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "---" + "---", + "\n", + "## Come accedere agli elementi (Indicizzazione, Chiavi e Slicing) 🎯\n", + "\n", + "Per accedere a un singolo elemento in una struttura dati si usano le **parentesi quadre `[]`**.\n", + "\n", + "- Per **Liste** e **Tuple**, si usa un **indice numerico**. L'indice parte da **0**. Indici negativi contano dalla fine (-1 è l'ultimo elemento).\n", + "```python\n", + "list_numbers = [10, 20, 30, 40, 50]\n", + "print(list_numbers[0]) # first element: 10\n", + "print(list_numbers[-1]) # last element: 50\n", + "```\n", + "- Per i **Dizionari**, si accede tramite la **chiave** associata al valore.\n", + "```python\n", + "user_data = {'name': 'Mario', 'age': 25}\n", + "print(user_data['name']) # Mario\n", + "```\n", + "- Per i **Set**, l'accesso diretto tramite `[]` non è possibile. Si può solo controllare se un elemento è presente con `in`.", + "\n", + "### Slicing: prendere più elementi in una volta\n", + "\n", + "Lo **slicing** permette di estrarre una parte di una sequenza (lista, tupla, stringa) senza modificare l'originale.\n", + "\n", + "Sintassi:\n", + "```python\n", + "sequence[start:stop:step]\n", + "```\n", + "- `start`: indice da cui iniziare (incluso), default = 0\n", + "- `stop`: indice dove fermarsi (escluso), default = fine sequenza\n", + "- `step`: quanti elementi saltare, default = 1\n", + "\n", + "Esempi:\n", + "```python\n", + "numbers = [10, 20, 30, 40, 50, 60]\n", + "\n", + "# From the third element to the end\n", + "print(numbers[2:]) # [30, 40, 50, 60]\n", + "\n", + "# From the second to the fourth element (fourth not included)\n", + "print(numbers[1:4]) # [20, 30, 40]\n", + "\n", + "# Get every two elements\n", + "print(numbers[::2]) # [10, 30, 50]\n", + "\n", + "# Reverse the list\n", + "print(numbers[::-1]) # [60, 50, 40, 30, 20, 10]\n", + "\n", + "# Using negative indices\n", + "print(numbers[-4:-1]) # [30, 40, 50]\n", + "```\n", + "\n" ] - }, +}, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 5. Iteratori e la parola chiave `for`\n", + "## Iteratori e la parola chiave `for`\n", "\n", "In Python, la maggior parte delle strutture dati, come liste, tuple e dizionari, sono **oggetti iterabili**. Un oggetto `iterable` è un contenitore che, quando gli viene richiesto, può produrre un **iteratore**.\n", "\n", @@ -390,7 +382,7 @@ "metadata": {}, "source": [ "---\n", - "## 6. La parola chiave `yield` 🔄\n", + "## La parola chiave `yield` 🔄\n", "\n", "In Python, la parola chiave **`yield`** viene usata all’interno di una funzione per trasformarla in un **generatore**. \n", "Un generatore è una funzione speciale che produce una sequenza di valori uno alla volta, **senza calcolare tutti i risultati in anticipo**. \n", @@ -427,7 +419,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 7. Spacchettare le collezioni: gli operatori `*` e `**`\n", + "## Spacchettare le collezioni: gli operatori `*` e `**`\n", "\n", "In Python, i caratteri `*` e `**` sono molto utili quando si lavora con le funzioni, specialmente per **spacchettare** (unpacking) il contenuto di collezioni come liste e dizionari, trasformandoli in argomenti singoli.\n", "\n", @@ -466,7 +458,6 @@ }, { "cell_type": "markdown", - "id": "c4b2f706", "metadata": {}, "source": [ "---\n", @@ -481,43 +472,106 @@ "In sintesi, Python ha scelto di non appesantire il linguaggio base con una struttura dati più rigida come l'array, preferendo la versatilità della lista e la potenza delle librerie esterne quando serve un'efficienza maggiore." ] }, - { +{ "cell_type": "markdown", "metadata": {}, "source": [ "---\n", -"## 8. Comprehensions ed Espressioni Generatrici \ud83c\udf1f\n", +"## Comprehensions ed Espressioni Generatrici 🌟\n", +"\n", +"Le *comprehensions* sono una delle caratteristiche più eleganti e potenti di Python. Permettono di creare nuove collezioni (liste, dizionari o insiemi) in modo **compatto**, **leggibile** e spesso più **efficiente** rispetto ai cicli tradizionali.\n", "\n", -"Le *comprehensions* sono una sintassi compatta e leggibile per creare nuove collezioni a partire da iterabili esistenti. Sono molto usate in Python per scrivere codice conciso e veloce.\n", +"Invece di scrivere diversi cicli `for` o usare funzioni come `map()` e `filter()`, possiamo combinare logica, iterazione e condizione in un'unica espressione chiara.\n", +"\n", +"---\n", +"### 🔹 List Comprehension\n", +"Le *list comprehensions* sono la forma più comune. Consentono di generare una lista a partire da un iterabile.\n", "\n", -"### List Comprehension\n", +"**Esempio base:**\n", "```python\n", -"# Create a list of squares of the numbers from 0 to 9\n", +"# Create a list of the squares of the numbers from 0 to 9\n", "squares = [x**2 for x in range(10)]\n", "print(squares)\n", +"# Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n", "```\n", "\n", -"### Dict Comprehension\n", +"**Esempio con condizione:**\n", "```python\n", -"# Create a dictionary with number:square\n", +"# Only the squares of even numbers\n", +"even_squares = [x**2 for x in range(10) if x % 2 == 0]\n", +"print(even_squares)\n", +"# Output: [0, 4, 16, 36, 64]\n", +"```\n", +"\n", +"Questo approccio sostituisce in modo più leggibile:\n", +"```python\n", +"squares = []\n", +"for x in range(10):\n", +" if x % 2 == 0:\n", +" squares.append(x**2)\n", +"```\n", +"\n", +"---\n", +"### 🔹 Dict Comprehension\n", +"Permettono di costruire un **dizionario** in un’unica riga.\n", +"\n", +"```python\n", +"# Create a number:square dictionary\n", "squares_dict = {x: x**2 for x in range(5)}\n", "print(squares_dict)\n", +"# Output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}\n", "```\n", "\n", -"### Set Comprehension\n", +"Le dict comprehensions sono utilissime, ad esempio, per invertire chiavi e valori:\n", "```python\n", -"# Create a set containing the cubes of the numbers\n", +"original = {'a': 1, 'b': 2, 'c': 3}\n", +"inverted = {v: k for k, v in original.items()}\n", +"print(inverted)\n", +"# Output: {1: 'a', 2: 'b', 3: 'c'}\n", +"```\n", +"\n", +"---\n", +"### 🔹 Set Comprehension\n", +"Gli *insiemi* (set) in Python non ammettono duplicati. Con una *set comprehension* possiamo creare facilmente collezioni di elementi unici.\n", +"\n", +"```python\n", +"# Create a set of number cubes\n", "cubes_set = {x**3 for x in range(5)}\n", "print(cubes_set)\n", +"# Output: {0, 1, 8, 27, 64}\n", "```\n", "\n", -"### Generator Expression\n", -"Simile a una list comprehension, ma produce un generatore, ossia gli elementi vengono calcolati su richiesta.\n", +"Un vantaggio importante è che, anche se un valore appare più volte nel ciclo, l’insieme lo terrà una sola volta.\n", +"\n", +"---\n", +"### 🔹 Generator Expression ⚙️\n", +"Le *generator expressions* sono molto simili alle list comprehensions, ma invece di creare l’intera lista in memoria, producono i valori **uno alla volta**, quando servono. Questo le rende ideali per lavorare con grandi quantità di dati o flussi infiniti.\n", +"\n", "```python\n", -"gen = (x**2 for x in range(5))\n", +"gen = (x**2 for x in range(5)) # use round brackets!\n", "for value in gen:\n", -" print(value)\n", -"```" +" print(value)\n", +"# Output: 0 1 4 9 16\n", +"```\n", +"\n", +"Una volta esaurito il generatore, non può essere riutilizzato (bisogna ricrearlo).\n", +"\n", +"**Esempio pratico:** calcolare la somma di numeri grandi senza creare una lista intermedia:\n", +"```python\n", +"total = sum(x for x in range(1_000_000)) # molto più efficiente!\n", +"print(total)\n", +"```\n", +"\n", +"---\n", +"### 🧠 Quando usare cosa\n", +"- Usa **list comprehensions** quando ti serve effettivamente una lista in memoria.\n", +"- Usa **dict** o **set comprehensions** per creare collezioni chiave-valore o insiemi unici.\n", +"- Usa **generator expressions** per flussi di dati o quando vuoi risparmiare memoria.\n", +"\n", +"Le comprehensions non sono solo sintatticamente più belle, ma spesso più veloci dei cicli tradizionali, grazie all’implementazione interna ottimizzata di Python.\n", +"\n", +"---\n", +"📘 **Curiosità storica:** Le comprehensions derivano direttamente dal linguaggio **Haskell** e, in parte, da **Set-builder notation** della matematica. Python le ha introdotte nella versione 2.0 (anno 2000), e da allora sono diventate uno standard nella scrittura di codice Pythonic.\n" ] }, { @@ -537,7 +591,7 @@ "metadata": {}, "source": [ "### Esercizio 1: Accesso agli elementi\n", - "Data una lista di colori `colours = ['yellow', 'orange', 'violet']`, una tupla di coordinate `coordinates = (45, 90)` e un dizionario `person = {'name': 'Paolo', 'city': 'Milano'}`, scrivi il codice per stampare:\n", + "Data una lista di colori `colours = ['yellow', 'orange', 'violet']`, una tupla di coordinate `coordinates = (45, 90)` e un dizionario `person = {'name': 'Paolo', 'city': 'Milano'}`, scrivere il codice per stampare:\n", "1. Il secondo colore (orange)\n", "2. L'ultimo elemento delle coordinate\n", "3. Il nome 'Paolo' dal dizionario" @@ -549,7 +603,7 @@ "metadata": {}, "source": [ "### Esercizio 2: Usare `join()`\n", - "Data la lista `url_parts = [\"https:\", \"\", \"www.python.org\", \"doc\"]`, usa il metodo `join()` per combinarla in un unico URL completo, utilizzando `//` come separatore per i primi due elementi e `/` per i successivi." + "Data la lista `url_parts = [\"https:\", \"\", \"www.python.org\", \"doc\"]`, usare il metodo `join()` per combinarla in un unico URL completo, utilizzando `//` come separatore per i primi due elementi e `/` per i successivi." ] }, { @@ -558,7 +612,7 @@ "metadata": {}, "source": [ "### Esercizio 3: Lista numeri\n", - "Crea una lista con 5 numeri, aggiungine uno e stampala ordinata." + "Creare una lista con 5 numeri, aggiungerne uno e stamparla ordinata." ] }, { @@ -567,7 +621,7 @@ "metadata": {}, "source": [ "### Esercizio 4: Tuple coordinate\n", - "Crea una tupla `coordinates` con due valori e stampa il primo." + "Creare una tupla `coordinates` con due valori e stampare il primo." ] }, { @@ -576,7 +630,7 @@ "metadata": {}, "source": [ "### Esercizio 5: Set animali\n", - "Crea un set con alcuni animali, aggiungi uno nuovo e stampa il risultato." + "Creare un set con alcuni animali, aggiungene uno nuovo e stampare il risultato." ] }, { @@ -585,7 +639,7 @@ "metadata": {}, "source": [ "### Esercizio 6: Dizionario studente\n", - "Crea un dizionario `student` con chiavi `name`, `age` e `course`. Stampane i valori." + "Creare un dizionario `student` con chiavi `name`, `age` e `course`. Stamparne i valori." ] }, { @@ -593,7 +647,7 @@ "metadata": {}, "source": [ "### Esercizio 7: Usare gli iteratori\n", - "Dato l'elenco di colori `colours = ['red', 'green', 'blue']`, simula il comportamento di un ciclo `for`. Ottieni l'iteratore dalla lista usando la funzione `iter()` e, all'interno di un ciclo `while` con un blocco `try-except`, stampa ogni elemento usando `next()`. Gestisci l'eccezione `StopIteration` per terminare il ciclo correttamente." + "Dato l'elenco di colori `colours = ['red', 'green', 'blue']`, simulare il comportamento di un ciclo `for`. Ottenere l'iteratore dalla lista usando la funzione `iter()` e, all'interno di un ciclo `while` con un blocco `try-except`, stampare ogni elemento usando `next()`. Gestire l'eccezione `StopIteration` per terminare il ciclo correttamente." ] }, { @@ -601,7 +655,7 @@ "metadata": {}, "source": [ "### Esercizio 8: Spacchettare una lista (*)\n", - "Data una funzione `sum_three_numbers(a, b, c)` che calcola la somma di tre numeri, e una lista `numbers = [10, 20, 30]`, usa l'operatore `*` per spacchettare la lista e passare i suoi elementi alla funzione. Stampa il risultato." + "Data una funzione `sum_three_numbers(a, b, c)` che calcola la somma di tre numeri, e una lista `numbers = [10, 20, 30]`, usare l'operatore `*` per spacchettare la lista e passare i suoi elementi alla funzione. Stampare il risultato." ] }, { @@ -609,7 +663,7 @@ "metadata": {}, "source": [ "### Esercizio 9: Spacchettare un dizionario (**)\n", - "Data una funzione `save_user(username, password)` e un dizionario `credentials = {'username': 'admin', 'password': 'password'}`, usa l'operatore `**` per spacchettare il dizionario e passare le credenziali alla funzione. La funzione dovrebbe stampare un messaggio di conferma." + "Data una funzione `save_user(username, password)` e un dizionario `credentials = {'username': 'admin', 'password': 'password'}`, usare l'operatore `**` per spacchettare il dizionario e passare le credenziali alla funzione. La funzione dovrebbe stampare un messaggio di conferma." ] }, { @@ -617,7 +671,7 @@ "metadata": {}, "source": [ "### Esercizio 10: List comprehension\n", -"Crea una lista con i quadrati dei numeri da 1 a 10 usando una *list comprehension*." +"Creare una lista con i quadrati dei numeri da 1 a 10 usando una *list comprehension*." ] }, { @@ -625,7 +679,7 @@ "metadata": {}, "source": [ "### Esercizio 11: Dict comprehension\n", -"Crea un dizionario che mappa le lettere di una stringa alla loro lunghezza, usando una *dict comprehension*. Usa la stringa `words = ['python', 'ai', 'data']`." +"Creare un dizionario che mappa le lettere di una stringa alla loro lunghezza, usando una *dict comprehension*. Usa la stringa `words = ['python', 'ai', 'data']`." ] }, { @@ -633,7 +687,7 @@ "metadata": {}, "source": [ "### Esercizio 12: Set comprehension\n", -"Crea un set contenente le prime lettere di ciascuna parola in una lista, usando una *set comprehension*." +"Creare un set contenente le prime lettere di ciascuna parola in una lista, usando una *set comprehension*." ] }, { @@ -641,7 +695,7 @@ "metadata": {}, "source": [ "### Esercizio 13: Generator expression\n", -"Usa una *generator expression* per calcolare il cubo dei numeri da 0 a 4 e stampare i risultati in un ciclo `for`." +"Usare una *generator expression* per calcolare il cubo dei numeri da 0 a 4 e stampare i risultati in un ciclo `for`." ] }, { diff --git a/04_gestione_errori.ipynb b/04_gestione_errori.ipynb index 751175f..f311afb 100755 --- a/04_gestione_errori.ipynb +++ b/04_gestione_errori.ipynb @@ -8,16 +8,16 @@ "\n", "---\n", "\n", - "In questo capitolo si descirve la gestone degli errori (eccezioni) che si verificano durante l'esecuzione del programma. Una corretta gestione degli errori è essenziale per rendere il codice più robusto e affidabile." + "In questo capitolo si descrive la gestone degli errori (eccezioni) che si verificano durante l'esecuzione del programma. Una corretta gestione degli errori è essenziale per rendere il codice più robusto e affidabile." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Tipi di errori comuni\n", + "## Tipi di errori comuni\n", "\n", - "Gli errori, o **eccezioni**, si verificano quando Python non può eseguire un'operazione. Se non gestite, interrompono l'esecuzione del programma. Qui sono riportati alcunu esempi delle eccezioni più comuni:\n", + "Gli errori, o **eccezioni**, si verificano quando Python non può eseguire un'operazione. Se non gestite, interrompono l'esecuzione del programma. Qui sono riportati alcuni esempi delle eccezioni più comuni:\n", "\n", "- `SyntaxError`: Errore di sintassi, come una parentesi mancante. Non può essere gestito con `try/except`.\n", "- `TypeError`: Errore di tipo, ad esempio, quando si cerca di sommare un numero a una stringa.\n", @@ -31,11 +31,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Dove si incontrano gli errori?\n", + "## Dove si incontrano gli errori?\n", "\n", "Gli errori in Python si possono incontrare in diversi momenti:\n", "\n", - "- **Durante la scrittura del codice (SyntaxError)**: se dimentichi una parentesi o scrivi un'istruzione non valida, Python lo segnala subito e il programma non viene eseguito.\n", + "- **Durante la scrittura del codice (SyntaxError)**: se si dimentica una parentesi o scrivi un'istruzione non valida, Python lo segnala subito e il programma non viene eseguito.\n", "\n", "- **Durante l'esecuzione (RuntimeError / eccezioni)**: il codice è sintatticamente corretto ma, quando va in esecuzione, succede qualcosa di imprevisto. Ad esempio:\n", " - divisione per zero → `ZeroDivisionError`\n", @@ -61,7 +61,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. Come leggere i messaggi di errore\n", + "## Come leggere i messaggi di errore\n", "\n", "Quando si verifica un errore, Python stampa una **traceback** (traccia):\n", "\n", @@ -82,9 +82,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 4. Blocchi try/except/else/finally\n", + "## Blocchi try/except/else/finally\n", "\n", - "Per prevenire che il programma si blocchi a causa di un errore, usiamo i blocchi **`try...except`**. Questa struttura ci permette di \"provare\" a eseguire un blocco di codice e, in caso di eccezione, di eseguire un altro blocco specifico per gestirla.\n", + "Per prevenire che il programma si blocchi a causa di un errore, vengono usati i blocchi **`try...except`**. Questa struttura permette di \"provare\" a eseguire un blocco di codice e, in caso di eccezione, di eseguire un altro blocco specifico per gestirla.\n", "\n", "- **`try`**: Il codice che potrebbe generare un errore viene inserito qui.\n", "- **`except [TipoErrore]`**: Questo blocco viene eseguito solo se si verifica l'errore specificato nel `try`.\n", @@ -118,12 +118,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 5. Best practice per gestire gli errori\n", + "## Best practice per gestire gli errori\n", "\n", - "- Usa `try/except` solo quando serve.\n", - "- Specifica l'eccezione giusta (es. `ValueError`) invece di usare sempre `except Exception`.\n", - "- Aggiungi messaggi chiari per l'utente.\n", - "- Usa `finally` per chiudere risorse, anche in caso di errore.\n", + "- Usare `try/except` solo quando serve.\n", + "- Specificare l'eccezione giusta (es. `ValueError`) invece di usare sempre `except Exception`.\n", + "- Aggiungere messaggi chiari per l'utente.\n", + "- Usare `finally` per chiudere risorse, anche in caso di errore.\n", "\n", "```python\n", "try:\n", @@ -136,7 +136,7 @@ "```" ] }, - { + { "cell_type": "markdown", "metadata": {}, "source": [ @@ -145,6 +145,39 @@ "---" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Esercizio 1: Divisione sicura\n", + "Scrivere un programma che chiede due numeri e li divide. Gestire sia l'errore di **divisione per zero** (`ZeroDivisionError`) che l'input non numerico (`ValueError`)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Esercizio 2: Accesso alla lista\n", + "Creare una lista con alcuni elementi. Chiedere all'utente di inserire un indice e stampa l'elemento corrispondente. Gestire gli errori `IndexError` (se l'indice è fuori range) e `ValueError` (se l'input non è un numero intero)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Esercizio 3: Convertire in int\n", + "Chiedere all'utente di inserire un numero. Usare un blocco `try` per gestire il caso in cui inserisce un testo che non può essere convertito in numero intero. Se la conversione ha successo, stampare il numero, altrimenti stampare un messaggio di errore." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Soluzioni\n", + "\n", + "---" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/05_funzioni_moduli.ipynb b/05_funzioni_moduli.ipynb index d01aa5f..783eb86 100755 --- a/05_funzioni_moduli.ipynb +++ b/05_funzioni_moduli.ipynb @@ -15,7 +15,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Funzioni: `def`\n", + "## Funzioni: `def`\n", "\n", "Una funzione è un blocco di codice che esegue un compito specifico e può essere richiamato più volte. Si definisce con la parola chiave `def`." ] @@ -42,11 +42,11 @@ "\n", "Gli **argomenti** (o parametri) sono i valori che vengono passati a una funzione per permetterle di eseguire il suo compito in modo dinamico. Vengono specificati tra parentesi nella definizione della funzione.\n", "\n", - "In Python, quando viene chiamata una funzione, puoi passare gli argomenti in due modi principali:\n", + "In Python, quando viene chiamata una funzione, si possono passare gli argomenti in due modi principali:\n", "\n", - "- **Argomenti posizionali**: L'ordine in cui li passi è importante. Python associa il primo valore passato al primo parametro, il secondo al secondo, e così via.\n", + "- **Argomenti posizionali**: L'ordine in cui vengono passati è importante. Python associa il primo valore passato al primo parametro, il secondo al secondo, e così via.\n", "\n", - "- **Argomenti nominali (keyword arguments)**: Specifichi esplicitamente il nome del parametro a cui assegnare il valore, rendendo l'ordine non vincolante e il codice più leggibile.\n" + "- **Argomenti nominali (keyword arguments)**: Si specifica esplicitamente il nome del parametro a cui assegnare il valore, rendendo l'ordine non vincolante e il codice più leggibile.\n" ] }, { @@ -157,7 +157,7 @@ "source": [ "### La parola chiave `pass`\n", "\n", - "La keyword **`pass`** in Python è un'istruzione che non fa nulla. Viene usata come **placeholder** quando la sintassi richiede un'istruzione ma tu non vuoi che venga eseguito alcun codice. Questo è utile per definire una funzione o una classe vuota che verrà implementata in un secondo momento, o per gestire un'eccezione senza dover fare nulla al suo interno." + "La keyword **`pass`** in Python è un'istruzione che non fa nulla. Viene usata come **placeholder** quando la sintassi richiede un'istruzione ma non si vuole che venga eseguito alcun codice. Questo è utile per definire una funzione o una classe vuota che verrà implementata in un secondo momento, o per gestire un'eccezione senza dover fare nulla al suo interno." ] }, { @@ -181,7 +181,7 @@ "source": [ "### Argomenti con valori di default ⚙️\n", "\n", - "Puoi assegnare un **valore predefinito** a un argomento direttamente nella definizione della funzione. Se l'utente non fornisce un valore per quell'argomento al momento della chiamata, verrà utilizzato il valore di default. Gli argomenti con valori predefiniti devono essere definiti **dopo** tutti gli argomenti senza un valore di default.\n", + "Si può assegnare un **valore predefinito** a un argomento direttamente nella definizione della funzione. Se l'utente non fornisce un valore per quell'argomento al momento della chiamata, verrà utilizzato il valore di default. Gli argomenti con valori predefiniti devono essere definiti **dopo** tutti gli argomenti senza un valore di default.\n", "\n", "Il valore predefinito può essere qualsiasi tipo di dato, incluso `None`." ] @@ -224,7 +224,7 @@ "```\n", "\n", "In questo caso:\n", - "- Se chiami la funzione senza specificare l'argomento `system`, il suo valore sarà `None`.\n", + "- Se la funzione viene chiamata senza specificare l'argomento `system`, il suo valore sarà `None`.\n", "- L'istruzione `if system:` controlla se `system` ha un valore diverso da `None` (o da altri valori considerati `False` in Python). Poiché `None` è `False`, la condizione `if` non viene soddisfatta e viene eseguita la seconda parte del blocco `else`.\n", "- Se invece passi un valore come `\"AI\"`, `system` non sarà più `None` e la condizione `if` sarà `True`, eseguendo il primo `print` che aggiunge il prefisso `[AI]`." ] @@ -271,15 +271,15 @@ "source": [ "---", "\n", - "## 2. Moduli: `import`\n", + "## Moduli: `import`\n", "\n", "Un **modulo** è un file Python (`.py`) che contiene definizioni di funzioni, classi e variabili. L'uso dei moduli ti permette di riutilizzare codice senza scriverlo ogni volta.\n", "\n", "### L'istruzione `import`\n", - "L'istruzione `import nome_modulo` importa l'intero modulo. Per usare una funzione, devi specificare il nome del modulo seguito da un punto (`.`), come in `math.sqrt()`.\n", + "L'istruzione `import nome_modulo` importa l'intero modulo. Per usare una funzione, occorre specificare il nome del modulo seguito da un punto (`.`), come in `math.sqrt()`.\n", "\n", "### L'istruzione `from ... import`\n", - "L'istruzione `from nome_modulo import elemento` ti permette di importare solo un elemento specifico (una funzione, una classe, una variabile) da un modulo. In questo modo, puoi usare l'elemento direttamente senza dover specificare il nome del modulo. Questo metodo rende il codice più conciso, ma può portare a conflitti di nomi se importi elementi con nomi uguali da moduli diversi." + "L'istruzione `from nome_modulo import elemento` permette di importare solo un elemento specifico (una funzione, una classe, una variabile) da un modulo. In questo modo, si può usare l'elemento direttamente senza dover specificare il nome del modulo. Questo metodo rende il codice più conciso, ma può portare a conflitti di nomi se importi elementi con nomi uguali da moduli diversi." ] }, { @@ -320,9 +320,9 @@ "source": [ "---", "\n", - "## 3. Strutturare un progetto Python: le cartelle 📁\n", + "## Strutturare un progetto Python: le cartelle 📁\n", "\n", - "Quando il tuo codice cresce, un'ottima pratica è organizzarlo in cartelle e file. Una cartella che contiene uno o più file `.py` e un file speciale chiamato `__init__.py` è chiamata **pacchetto**.\n", + "Quando il codice cresce, un'ottima pratica è organizzarlo in cartelle e file. Una cartella che contiene uno o più file `.py` e un file speciale chiamato `__init__.py` è chiamata **pacchetto**.\n", "\n", "Un progetto Python ben strutturato rende il codice più leggibile, gestibile e facile da condividere. Ecco un esempio di una struttura di base:" ] @@ -399,7 +399,7 @@ "metadata": {}, "source": [ "### Esercizio 1: Funzione personalizzata\n", - "Crea una funzione `calculate_rectangle_area(base, height)` che restituisca l'area di un rettangolo. Chiamala con dei valori a tua scelta." + "Creare una funzione `calculate_rectangle_area(base, height)` che restituisca l'area di un rettangolo. Chiamarla con dei valori a scelta." ] }, { @@ -414,7 +414,7 @@ "metadata": {}, "source": [ "### Esercizio 2: Funzione con argomento opzionale\n", - "Scrivi una funzione `greet(name, message)` che stampi un messaggio di benvenuto. L'argomento `message` deve essere opzionale, con un valore di default `Hello`." + "Scrivere una funzione `greet(name, message)` che stampi un messaggio di benvenuto. L'argomento `message` deve essere opzionale, con un valore di default `Hello`." ] }, { @@ -429,7 +429,7 @@ "metadata": {}, "source": [ "### Esercizio 3: Usare il modulo `datetime`\n", - "Importa il modulo `datetime` e stampa la data e l'ora attuali usando `datetime.datetime.now()`." + "Importare il modulo `datetime` e stampare la data e l'ora attuali usando `datetime.datetime.now()`." ] }, { @@ -444,7 +444,7 @@ "metadata": {}, "source": [ "### Esercizio 4: Gestire la struttura di un progetto\n", - "Considera la seguente struttura di progetto. Il file `geometry.py` contiene una funzione per calcolare l'area di un rettangolo. Scrivi il codice che andrebbe nel file `main.py` per importare e usare questa funzione.\n", + "Considerare la seguente struttura di progetto. Il file `geometry.py` contiene una funzione per calcolare l'area di un rettangolo. Scrivere il codice che andrebbe nel file `main.py` per importare e usare questa funzione.\n", "\n", "Struttura:\n", "```text\n", @@ -461,7 +461,7 @@ " return base * height\n", "```\n", "\n", - "Scrivi il codice per `main.py` per calcolare e stampare l'area di un rettangolo con base `10` e altezza `5`." + "Scrivere il codice per `main.py` per calcolare e stampare l'area di un rettangolo con base `10` e altezza `5`." ] }, { @@ -476,7 +476,7 @@ "metadata": {}, "source": [ "### Esercizio 5: Funzione come argomento\n", - "Crea una funzione `apply_format(str, format)` che prenda una stringa e una funzione `format` come argomenti. L'obiettivo è far sì che `apply_format` chiami la funzione `format` con la stringa e stampi il risultato. Poi, crea due funzioni, `lower_case` e `upper_case`, e usale come argomenti per `apply_format`." + "Creare una funzione `apply_format(str, format)` che prenda una stringa e una funzione `format` come argomenti. L'obiettivo è far sì che `apply_format` chiami la funzione `format` con la stringa e stampi il risultato. Poi, creare due funzioni, `lower_case` e `upper_case`, e usarle come argomenti per `apply_format`." ] }, { diff --git a/06_fileio.ipynb b/06_fileio.ipynb index ecc7f7b..db6bf0c 100755 --- a/06_fileio.ipynb +++ b/06_fileio.ipynb @@ -13,9 +13,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Aprire e Chiudere un File\n", + "## Aprire e Chiudere un File\n", "\n", - "Per interagire con un file, devi prima aprirlo usando la funzione `open()`. Questa funzione restituisce un oggetto file e richiede almeno due argomenti:\n", + "Per interagire con un file, occorre prima aprirlo usando la funzione `open()`. Questa funzione restituisce un oggetto file e richiede almeno due argomenti:\n", "\n", "1. **Percorso del file** (`path`): il nome del file (se si trova nella stessa cartella) o il percorso completo.\n", "2. **Modalità di apertura** (`mode`): una stringa che specifica lo scopo con cui apri il file.\n", @@ -57,9 +57,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Scrivere su un File\n", + "## Scrivere su un File\n", "\n", - "Una volta aperto un file in modalità scrittura (`\"w\"`) o aggiunta (`\"a\"`), puoi usare il metodo `.write()` per scriverci del testo. Il metodo accetta una stringa come argomento." + "Una volta aperto un file in modalità scrittura (`\"w\"`) o aggiunta (`\"a\"`), si può usare il metodo `.write()` per scriverci del testo. Il metodo accetta una stringa come argomento." ] }, { @@ -81,7 +81,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "**Attenzione:** il carattere `\\n` serve per andare a capo. Se non lo metti, il testo verrà scritto sulla stessa riga." + "**Attenzione:** il carattere `\\n` serve per andare a capo. Se viene omesso, il testo verrà scritto sulla stessa riga." ] }, { @@ -109,9 +109,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. Leggere da un File\n", + "## Leggere da un File\n", "\n", - "Per leggere il contenuto di un file, aprilo in modalità lettura (`\"r\"`). Puoi usare diversi metodi:\n", + "Per leggere il contenuto di un file, bisogna aprirlo in modalità lettura (`\"r\"`). Si possono usare diversi metodi:\n", "- `.read()`: legge l'intero contenuto del file e lo restituisce come una singola stringa.\n", "- `.readline()`: legge una singola riga del file.\n", "- `.readlines()`: legge tutte le righe del file e le restituisce come una lista di stringhe." @@ -152,39 +152,116 @@ "---" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4. Il costrutto `with open(...) as ...`\n", - "\n", - "Il modo migliore e più sicuro per gestire i file è usare il costrutto `with`. Questo gestore di contesto si occupa automaticamente di chiudere il file, anche se si verificano errori all'interno del blocco `with`. È una best practice consigliata per prevenire perdite di risorse." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Example using 'with'\n", - "with open(\"data.txt\", \"w\") as f:\n", - " f.write(\"This text has been written using with.\")\n", - "\n", - "print(\"File closed.\")\n", - "\n", - "# Read the file in a secure way\n", - "with open(\"dati.txt\", \"r\") as f:\n", - " content = f.read()\n", - " print(content)" - ] - }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Il costrutto `with open(...) as ...`\n", + "\n", + "Il modo più **sicuro**, **pulito** per lavorare con i file è usare il costrutto `with`. Questo costrutto è noto come **gestore di contesto** (*context manager*), e serve a garantire che le risorse vengano gestite correttamente.\n", + "\n", + "Quando si apre un file in Python, è buona pratica chiuderlo sempre dopo l'uso, altrimenti il programma può consumare risorse inutilmente o bloccare l’accesso ad altri processi. Scrivere `f.close()` a mano, però, è soggetto a errori. Il costrutto `with` risolve questo problema automaticamente.\n", + "\n", + "---\n", + "### 🧠 Come funziona\n", + "\n", + "La sintassi è la seguente:\n", + "\n", + "```python\n", + "with open('file.txt', 'mode') as variabile:\n", + " # blocco di codice che lavora con il file\n", + " ...\n", + "# fuori dal blocco il file è già chiuso automaticamente\n", + "```\n", + "\n", + "Il file viene **aperto all’inizio del blocco** e **chiuso automaticamente** al termine, anche in caso di errore o eccezione.\n", + "\n", + "---\n", + "### ✍️ Esempio di scrittura in un file\n", + "\n", + "```python\n", + "with open('data.txt', 'w') as f:\n", + " f.write('Questo testo è stato scritto usando with.')\n", + " f.write('\\nScrivere con with è sicuro e semplice!')\n", + "\n", + "print('Il file è stato scritto e chiuso automaticamente.')\n", + "```\n", + "\n", + "- Il secondo argomento `'w'` significa *write mode*: il file viene creato o sovrascritto.\n", + "- Se il file non esiste, viene creato.\n", + "- Se esiste, il suo contenuto viene cancellato prima di scrivere.\n", + "\n", + "---\n", + "### 📖 Esempio di lettura da un file\n", + "\n", + "```python\n", + "with open('data.txt', 'r') as f:\n", + " content = f.read()\n", + " print('Contenuto del file:')\n", + " print(content)\n", + "```\n", + "\n", + "- `'r'` significa *read mode*: il file viene aperto in sola lettura.\n", + "- Se il file non esiste, Python solleva un `FileNotFoundError`.\n", + "\n", + "---\n", + "### ➕ Aggiungere contenuto a un file (append)\n", + "\n", + "```python\n", + "with open('data.txt', 'a') as f:\n", + " f.write('\\nNuova riga aggiunta in append.')\n", + "```\n", + "\n", + "- `'a'` significa *append mode*: il contenuto viene aggiunto in fondo al file, senza cancellare quello esistente.\n", + "\n", + "---\n", + "### 🧩 Lettura riga per riga\n", + "Invece di leggere tutto il file in un’unica stringa, si può scorrere il file riga per riga:\n", + "\n", + "```python\n", + "with open('data.txt', 'r') as f:\n", + " for line in f:\n", + " print(line.strip()) # .strip() rimuove i caratteri di newline\n", + "```\n", + "\n", + "Questo approccio è più efficiente per file di grandi dimensioni, poiché non carica tutto in memoria.\n", + "\n", + "---\n", + "### ⚙️ Modalità di apertura più comuni\n", + "\n", + "| Modalità | Significato | Descrizione breve |\n", + "|-----------|--------------|------------------|\n", + "| `'r'` | Read | Lettura (errore se il file non esiste) |\n", + "| `'w'` | Write | Scrittura (sovrascrive il file) |\n", + "| `'a'` | Append | Aggiunge in fondo al file |\n", + "| `'r+'` | Read/Write | Lettura e scrittura nello stesso file |\n", + "| `'b'` | Binary | Modalità binaria (es. immagini, PDF, audio) |\n", + "\n", + "Si possono combinare le modalità, ad esempio `'rb'` o `'wb'`.\n", + "\n" + ] +}, +{ + "cell_type": "code", + "metadata": {}, + "execution_count": null, + "outputs": [], + "source": [ + "with open('data.txt', 'w', encoding='utf-8') as f:\n", + " f.write('Prima riga\\n')\n", + " f.write('Seconda riga')\n", + "\n", + "with open('data.txt', 'r', encoding='utf-8') as f:\n", + " print('Contenuto del file:')\n", + " print(f.read())" + ] +}, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", - "## 5. Streaming e file di grandi dimensioni 💾\n", + "## Streaming e file di grandi dimensioni 💾\n", "\n", "Quando si lavora con file di grandi dimensioni, leggere tutto il contenuto in memoria può causare problemi. Si possono usare due approcci per ovviare al problema, leggere il file **riga per riga** o in **blocchi** usando un ciclo o generatori.\n", "\n", @@ -226,10 +303,10 @@ "## Esercizi\n", "\n", "### Esercizio 1: Scrivere una lista su un file\n", - "Scrivi un programma che crea una lista di nomi e poi scrive ogni nome su una riga separata di un file `names.txt`.\n", + "Scrivere un programma che crea una lista di nomi e poi scrivere ogni nome su una riga separata di un file `names.txt`.\n", "\n", "### Esercizio 2: Leggere e contare le righe\n", - "Leggi il file `names.txt` creato nell'esercizio precedente e stampa il numero totale di righe (nomi)." + "Leggere il file `names.txt` creato nell'esercizio precedente e stampare il numero totale di righe (nomi)." ] }, { diff --git a/07_libreria_standard.ipynb b/07_libreria_standard.ipynb index 14c30c7..8cc490c 100755 --- a/07_libreria_standard.ipynb +++ b/07_libreria_standard.ipynb @@ -17,7 +17,7 @@ "id": "4cf41e6b", "metadata": {}, "source": [ - "## 1. Modulo `os`\n", + "## Modulo `os`\n", "\n", "Il modulo `os` (Operating System) fornisce un modo per interagire con il sistema operativo. È utile per manipolare file e directory, ottenere informazioni sul percorso, e molto altro." ] @@ -59,7 +59,7 @@ "id": "dabe4f28", "metadata": {}, "source": [ - "## 2. Modulo `sys`\n", + "## Modulo `sys`\n", "\n", "Il modulo `sys` fornisce l'accesso a variabili e funzioni relative all'interprete Python e al sistema su cui sta girando. È utile per manipolare il percorso di ricerca dei moduli o uscire dal programma." ] @@ -95,7 +95,7 @@ "id": "272c91dc", "metadata": {}, "source": [ - "## 3. Modulo `datetime`\n", + "## Modulo `datetime`\n", "\n", "Il modulo `datetime` è essenziale per lavorare con date e orari. Permette di creare, formattare e manipolare oggetti data e ora in modo semplice." ] @@ -134,7 +134,7 @@ "id": "6eda268c", "metadata": {}, "source": [ - "## 4. Modulo `random`\n", + "## Modulo `random`\n", "\n", "Il modulo `random` è utilizzato per generare numeri casuali. È molto utile per simulazioni, giochi o per scegliere elementi a caso da una sequenza." ] @@ -171,7 +171,7 @@ "id": "8f8955f2", "metadata": {}, "source": [ - "## 5. Metodi delle Stringhe: Manipolazione e Formattazione ✍️\n", + "## Metodi delle Stringhe: Manipolazione e Formattazione ✍️\n", "\n", "Le stringhe in Python non sono solo sequenze di caratteri, ma veri e propri oggetti con una vasta gamma di metodi integrati per manipolarle e formattarle in modo efficiente. A differenza di molti moduli della libreria standard, questi metodi non richiedono un `import` e possono essere chiamati direttamente sulla stringa stessa.\n", "\n", @@ -209,7 +209,7 @@ "id": "3e370f48", "metadata": {}, "source": [ - "## 6. Modulo `json`\n", + "## Modulo `json`\n", "\n", "Il modulo `json` permette di lavorare con dati in formato **JSON (JavaScript Object Notation)**, che è un formato molto comune per lo scambio di dati tra applicazioni web. Permette di convertire oggetti Python in stringhe JSON e viceversa." ] @@ -254,17 +254,17 @@ "## Esercizi\n", "\n", "### Esercizio 1: Data di oggi\n", - "Usa il modulo `datetime` per stampare la data di oggi formattata come `gg-mm-aaaa`.\n", + "Usare il modulo `datetime` per stampare la data di oggi formattata come `gg-mm-aaaa`.\n", "\n", "### Esercizio 2: Scelta casuale\n", - "Data una lista di numeri `[10, 20, 30, 40, 50]`, usa il modulo `random` per scegliere e stampare un numero a caso da essa.\n", + "Data una lista di numeri `[10, 20, 30, 40, 50]`, usare il modulo `random` per scegliere e stampare un numero a caso da essa.\n", "\n", "### Esercizio 3: Manipolare una stringa\n", "Data la stringa `text = \" Hello, python is a FANTASTIC language! \"`:\n", - "1. Rimuovi gli spazi iniziali e finali.\n", - "2. Sostituisci la parola \"FANTASTIC\" con \"incredible\".\n", - "3. Converti l'intera frase in minuscolo.\n", - "Stampa il risultato finale." + "1. Rimuovere gli spazi iniziali e finali.\n", + "2. Sostituire la parola \"FANTASTIC\" con \"incredible\".\n", + "3. Convertire l'intera frase in minuscolo.\n", + "Stampare il risultato finale." ] }, { diff --git a/08_librerie.ipynb b/08_librerie.ipynb index 597a292..047634e 100755 --- a/08_librerie.ipynb +++ b/08_librerie.ipynb @@ -2,13 +2,11 @@ "cells": [ { "cell_type": "markdown", - "id": "df0febe4", + "id": "401a54c9", "metadata": {}, "source": [ "# 🌐 Gestione di Pacchetti e Ambienti Virtuali\n", - "\n", - "---\n", - "Oltre alla Libreria Standard di Python, la community ha creato migliaia di pacchetti esterni che offrono funzionalità aggiuntive. Per gestirli in modo efficiente e professionale, vengono usati due strumenti fondamentali: **pip** e gli **ambienti virtuali**." + "Oltre alla Libreria Standard di Python, la community ha creato migliaia di pacchetti esterni che offrono funzionalità aggiuntive. Per gestirli in modo efficiente e professionale, vengono usati due strumenti fondamentali: pip e gli ambienti virtuali." ] }, { @@ -16,7 +14,7 @@ "id": "9c69c247", "metadata": {}, "source": [ - "## 1. Gestore di pacchetti: `pip`\n", + "## Gestore di pacchetti: `pip`\n", "\n", "**`pip`** è il gestore di pacchetti ufficiale di Python. Permette di installare, disinstallare e gestire librerie esterne in modo semplice e veloce, attingendo al vastissimo repository di pacchetti chiamato **PyPI (Python Package Index)**." ] @@ -64,7 +62,7 @@ "id": "19070cf2", "metadata": {}, "source": [ - "## 2. Trovare librerie e consultare la documentazione\n", + "## Trovare librerie e consultare la documentazione\n", "\n", "Per un programmatore, trovare la libreria giusta e imparare a usarla sono passaggi cruciali. Le risorse principali sono due:" ] @@ -75,7 +73,7 @@ "metadata": {}, "source": [ "### A. **PyPI (Python Package Index)**\n", - "**PyPI** è il catalogo ufficiale di tutti i pacchetti Python. Quando usi `pip install`, è da qui che i pacchetti vengono scaricati. Puoi navigare sul sito `https://pypi.org/` per cercare librerie per nome o per parola chiave, e ogni pagina di un pacchetto ti fornirà il comando esatto da usare per l'installazione." + "**PyPI** è il catalogo ufficiale di tutti i pacchetti Python. Quando si usa `pip install`, è da qui che i pacchetti vengono scaricati. E' possibile navigare sul sito `https://pypi.org/` per cercare librerie per nome o per parola chiave, e ogni pagina di un pacchetto fornirà il comando esatto da usare per l'installazione." ] }, { @@ -84,15 +82,15 @@ "metadata": {}, "source": [ "### B. **La documentazione (API)**\n", - "L'**API (Application Programming Interface)** di una libreria è l'insieme di istruzioni, funzioni e classi che puoi usare per interagire con essa. La documentazione ufficiale è la fonte più affidabile per capire come funziona una libreria.\n", + "L'**API (Application Programming Interface)** di una libreria è l'insieme di istruzioni, funzioni e classi che si possono usare per interagire con essa. La documentazione ufficiale è la fonte più affidabile per capire come funziona una libreria.\n", "\n", "In genere, la documentazione è strutturata in:\n", "\n", - "* **Guida rapida (Quick Start)**: ti mostra gli esempi di base per iniziare.\n", - "* **Guide (Guides)**: ti spiega in dettaglio i concetti chiave.\n", + "* **Guida rapida (Quick Start)**: vengono mostrati gli esempi di base per iniziare.\n", + "* **Guide (Guides)**: vengono spiegati in dettaglio i concetti chiave.\n", "* **Riferimento API (API Reference)**: elenca ogni singola funzione, i suoi parametri e il valore di ritorno. \n", "\n", - "Ad esempio, per la libreria `requests`, la documentazione si trova su `https://requests.readthedocs.io/`. Consultandola, puoi imparare a usare funzioni come `requests.get()` o `requests.post()` in tutti i loro dettagli." + "Ad esempio, per la libreria `requests`, la documentazione si trova su `https://requests.readthedocs.io/`. Consultandola, si può imparare a usare funzioni come `requests.get()` o `requests.post()` in tutti i loro dettagli." ] }, { @@ -108,9 +106,9 @@ "id": "6c55d41d", "metadata": {}, "source": [ - "## 3. Ambienti virtuali: `venv`\n", + "## Ambienti virtuali: `venv`\n", "\n", - "Un **ambiente virtuale** è una directory isolata che contiene una copia di un interprete Python e i pacchetti specifici per un progetto. Questo ti permette di lavorare su progetti diversi senza che le loro dipendenze entrino in conflitto. " + "Un **ambiente virtuale** è una directory isolata che contiene una copia di un interprete Python e i pacchetti specifici per un progetto. Questo permette di lavorare su progetti diversi senza che le loro dipendenze entrino in conflitto. " ] }, { @@ -149,7 +147,7 @@ "id": "84a834e5", "metadata": {}, "source": [ - "Una volta attivato, vedrai il nome dell'ambiente virtuale (`(venv)`) all'inizio della riga di comando. Tutti i pacchetti che installerai con `pip` da quel momento in poi saranno isolati in questo ambiente." + "Una volta attivato, sarà visibile il nome dell'ambiente virtuale (`(venv)`) all'inizio della riga di comando. Tutti i pacchetti che verranno installati con `pip` da quel momento in poi saranno isolati in questo ambiente." ] }, { @@ -159,11 +157,11 @@ "source": [ "### `requirements.txt`\n", "\n", - "Il file `requirements.txt` è un elenco di tutte le **dipendenze** di un progetto Python, cioè i pacchetti esterni che il tuo codice utilizza.\n", + "Il file `requirements.txt` è un elenco di tutte le **dipendenze** di un progetto Python, cioè i pacchetti esterni che il codice utilizza.\n", "\n", "Avere questo file è utile per diversi motivi:\n", "\n", - "1. **Riproducibilità:** chiunque voglia eseguire il tuo progetto può installare esattamente le stesse versioni dei pacchetti che hai usato, evitando problemi di compatibilità.\n", + "1. **Riproducibilità:** chiunque voglia eseguire il tuo progetto può installare esattamente le stesse versioni dei pacchetti che sono stati usati, evitando problemi di compatibilità.\n", "2. **Collaborazione:** quando si lavora in team, tutti possono avere un ambiente identico usando lo stesso file `requirements.txt`.\n", "3. **Automazione:** strumenti come `pip` possono leggere direttamente il file per installare tutte le dipendenze in un solo comando:\n", " ```bash\n", @@ -179,7 +177,7 @@ "```\n", "- `==` indica una versione **esatta**.\n", "- `>=` indica una versione **minima**.\n", - "- Se non specifichi la versione, pip installerà l'ultima disponibile.\n", + "- Se non viene specificata la versione, pip installerà l'ultima disponibile.\n", "\n", "In sintesi, `requirements.txt` è un modo semplice e standard per documentare e condividere le dipendenze di un progetto Python, fondamentale per la portabilità e la gestione del codice." ] @@ -222,7 +220,7 @@ "source": [ "### `requests` - Richieste HTTP \n", "\n", - "La libreria **Requests** è lo standard de facto in Python per inviare richieste HTTP.Nasce per rendere più leggibile e user-friendly l’interazione con servizi web e API RESTful, evitando la complessità delle librerie standard come `urllib`. \n", + "La libreria **Requests** è lo standard de facto in Python per inviare richieste HTTP. Nasce per rendere più leggibile e user-friendly l’interazione con servizi web e API RESTful, evitando la complessità delle librerie standard come `urllib`. \n", "\n", "#### 📌 Dove trovare la documentazione\n", "La documentazione ufficiale è disponibile su: [https://requests.readthedocs.io/](https://requests.readthedocs.io/). \n", @@ -448,7 +446,7 @@ "## Esercizi\n", "\n", "### Esercizio 1: Calcoli con NumPy\n", - "Crea un array NumPy di 10 numeri casuali interi tra 1 e 50. Trova il valore massimo, minimo e la media di questi numeri." + "Creare un array NumPy di 10 numeri casuali interi tra 1 e 50. Trovare il valore massimo, minimo e la media di questi numeri." ] }, { @@ -465,7 +463,7 @@ "metadata": {}, "source": [ "### Esercizio 2: Analisi Dati con Pandas\n", - "Crea un DataFrame con i seguenti dati (colonne 'Product', 'Quantity', 'Price'):\n", + "Creare un DataFrame con i seguenti dati (colonne 'Product', 'Quantity', 'Price'):\n", "\n", "| Product | Quantity | Price |\n", "|----------|----------|--------|\n", @@ -473,7 +471,7 @@ "| Bananas | 5 | 0.80 |\n", "| Ornages | 15 | 1.50 |\n", "\n", - "Calcola e stampa il prezzo totale per ogni prodotto (`Quantity * Price`)." + "Calcolare e stampare il prezzo totale per ogni prodotto (`Quantity * Price`)." ] }, { @@ -490,7 +488,7 @@ "metadata": {}, "source": [ "### Esercizio 3: Grafico con Matplotlib\n", - "Utilizzando Matplotlib, crea un semplice grafico a barre che mostri le quantità di frutta del DataFrame dell'esercizio precedente. Sull'asse X ci siano i nomi dei frutti e sull'asse Y le quantità." + "Utilizzando Matplotlib, creare un semplice grafico a barre che mostri le quantità di frutta del DataFrame dell'esercizio precedente. Sull'asse X ci siano i nomi dei frutti e sull'asse Y le quantità." ] }, { @@ -520,7 +518,7 @@ "Contacts are: pyhton@hanam.ai, info@hanam.ai, support@hanam.ai\n", "```\n", "\n", - "Usa la libreria `re` per:\n", + "Usare la libreria `re` per:\n", "1. Estrarre tutte le email dal testo.\n", "2. Sostituire i domini delle email con `***.com` (es: `pyhton@hanam.ai` diventa `pyhton@***.ai`)." ], diff --git a/09_oop.ipynb b/09_oop.ipynb index c3c0bfe..a276ad5 100755 --- a/09_oop.ipynb +++ b/09_oop.ipynb @@ -15,13 +15,13 @@ "id": "c612dfe5", "metadata": {}, "source": [ - "## 1. Classi e Oggetti\n", + "## Classi e Oggetti\n", "\n", "### Classe\n", "Una **classe** è un modello per creare oggetti. Definisce le proprietà comuni (attributi) e le azioni (metodi) che tutti gli oggetti di quel tipo avranno.\n", "\n", "### Oggetto\n", - "Un **oggetto** è una singola istanza di una classe. Quando crei un oggetto da una classe, stai creando un'entità concreta che ha i propri dati specifici." + "Un **oggetto** è una singola istanza di una classe. Quando si crea un oggetto da una classe, si sta in realtà creando un'entità concreta che ha i propri dati specifici." ] }, { @@ -56,7 +56,7 @@ "id": "b5feb8c0", "metadata": {}, "source": [ - "## 2. Attributi e Metodi\n", + "## Attributi e Metodi\n", "\n", "### Attributi\n", "Gli **attributi** sono le variabili che contengono i dati di un oggetto. Vengono solitamente definiti all'interno del metodo speciale `__init__`.\n", @@ -84,7 +84,7 @@ "class Person:\n", " # Constructor\n", " def __init__(self, name, age):\n", - " # Assegna i valori passati agli attributi dell'istanza\n", + " # Assigns the passed values to the instance's attributes\n", " self.name = name\n", " self.age = age\n", "\n", @@ -112,7 +112,7 @@ "id": "1d08ab98", "metadata": {}, "source": [ - "## 3. L'ereditarietà\n", + "## L'ereditarietà\n", "\n", "L'**ereditarietà** è un meccanismo che permette a una nuova classe (la **sottoclasse** o classe figlia) di ereditare gli attributi e i metodi di una classe esistente (la **superclasse** o classe genitore). Questo promuove il riutilizzo del codice." ] @@ -161,7 +161,7 @@ "id": "719c17f4", "metadata": {}, "source": [ - "## 4. Incapsulamento: Dati Protetti 🔒\n", + "## Incapsulamento: Dati Protetti 🔒\n", "\n", "L'**incapsulamento** è un principio fondamentale dell'OOP che consiste nel nascondere i dettagli interni di un oggetto e proteggerne i dati dall'accesso diretto ed esterno. In Python, usiamo delle convenzioni per indicare che un attributo non dovrebbe essere modificato direttamente:\n", "- Un singolo underscore (`_`) suggerisce che l'attributo è **protetto** (`_attributo_protetto`).\n", @@ -212,7 +212,7 @@ "id": "b73c734e", "metadata": {}, "source": [ - "## 5. L'operatore `isinstance()`: Controllo del Tipo 🤔\n", + "## L'operatore `isinstance()`: Controllo del Tipo 🤔\n", "\n", "L'operatore integrato `isinstance()` è una funzione molto utile per verificare se un oggetto è un'**istanza** di una determinata classe o di una delle sue sottoclassi.\n", "\n", @@ -220,14 +220,14 @@ "```python\n", "isinstance(oggetto, classe)\n", "```\n", - "- `oggetto`: L'istanza che vuoi verificare.\n", - "- `classe`: La classe (o una tupla di classi) rispetto a cui vuoi fare la verifica.\n", + "- `oggetto`: L'istanza che si vuole verificare.\n", + "- `classe`: La classe (o una tupla di classi) rispetto a cui si vuole fare la verifica.\n", "\n", "La funzione ritorna `True` se l'oggetto è del tipo specificato (o di una delle sue sottoclassi), altrimenti `False`.\n", "\n", - "Python, essendo un linguaggio a tipizzazione dinamica, incoraggia il cosiddetto **duck typing** (se un oggetto cammina come un'anatra e starnazza come un'anatra, allora è un'anatra), basato sul comportamento dell'oggetto (cioè sui metodi che ha). Tuttavia, `isinstance()` è indispensabile in diverse situazioni:\n", + "Python, essendo un linguaggio a tipizzazione dinamica, incoraggia il cosiddetto **duck typing**, basato sul comportamento dell'oggetto (cioè sui metodi che ha). Tuttavia, `isinstance()` è indispensabile in diverse situazioni:\n", "\n", - "- Quando hai bisogno di agire in modo diverso in base al **tipo esatto** di un oggetto.\n", + "- Quando si ha bisogno di agire in modo diverso in base al **tipo esatto** di un oggetto.\n", "- Per verificare che un oggetto sia conforme a un'**interfaccia** o a una classe astratta specifica.\n", "- Per garantire la compatibilità con librerie esterne che si aspettano tipi specifici.\n", "\n", @@ -270,7 +270,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 6. L'operatore `is` vs `==`: Identità e Uguaglianza 🔍\n", + "## L'operatore `is` vs `==`: Identità e Uguaglianza 🔍\n", "\n", "In Python esistono due modi diversi di confrontare gli oggetti:\n", "\n", @@ -305,9 +305,9 @@ "id": "c5de76d0", "metadata": {}, "source": [ - "## 7. Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n", + "## Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n", "\n", - "Il **polimorfismo** permette a oggetti di classi diverse di rispondere in modo specifico allo stesso metodo. Questo rende il tuo codice più flessibile e facile da estendere." + "Il **polimorfismo** permette a oggetti di classi diverse di rispondere in modo specifico allo stesso metodo. Questo rende il codice più flessibile e facile da estendere." ] }, { @@ -353,7 +353,7 @@ "id": "f92678a7", "metadata": {}, "source": [ - "## 8. Classi Astratte 📝\n", + "## Classi Astratte 📝\n", "\n", "Una **classe astratta** serve come modello e non può essere istanziata direttamente. Contiene uno o più **metodi astratti** (metodi senza implementazione), che devono essere obbligatoriamente implementati da qualsiasi sottoclasse che eredita da essa. Questo garantisce una struttura comune per tutte le classi derivate.\n", "\n", @@ -397,9 +397,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 9. Eccezioni personalizzate\n", + "## Eccezioni personalizzate\n", "\n", - "Ora che sono state introdotte le classi, possiamo vedere come usarle per creare eccezioni personalizzate. Oltre alle eccezioni predefinite, possiamo **creare eccezioni personalizzate** per gestire situazioni specifiche del nostro programma.\n", + "Ora che sono state introdotte le classi, possiamo vedere come usarle per creare eccezioni personalizzate. Oltre alle eccezioni predefinite, si possono **creare eccezioni personalizzate** per gestire situazioni specifiche del programma.\n", "\n", "Per creare un'eccezione personalizzata, si definisce una **nuova classe** che eredita da `Exception`:\n", "\n", @@ -438,22 +438,22 @@ "## Esercizi\n", "\n", "### Esercizio 1: Creazione di una classe `Car`\n", - "Crea una classe `Car` con un costruttore che accetta `model` e `brand` come argomenti. Crea un oggetto `car` e stampa i suoi attributi.\n", + "Creare una classe `Car` con un costruttore che accetta `model` e `brand` come argomenti. Creare un oggetto `car` e stampare i suoi attributi.\n", "\n", "### Esercizio 2: Aggiungi un metodo\n", - "Alla classe `Car` dell'esercizio precedente, aggiungi un metodo chiamato `show_details()` che stampa una frase come \"I own a [model] [brand]\". Chiamalo sul tuo oggetto `car`.\n", + "Alla classe `Car` dell'esercizio precedente, aggiungere un metodo chiamato `show_details()` che stampa una frase come \"I own a [model] [brand]\".\n", "\n", "### Esercizio 3: Classe `Animal` e sottoclassi\n", - "Crea una classe astratta `Animal` con un metodo astratto `sound()`. Crea poi due sottoclassi, `Lion` e `Cow`, che implementano il metodo `sound()` per stampare il suono corretto.\n", + "Creare una classe astratta `Animal` con un metodo astratto `sound()`. Creare poi due sottoclassi, `Lion` e `Cow`, che implementano il metodo `sound()` per stampare il suono corretto.\n", "\n", "### Esercizio 4: Polimorfismo in azione\n", - "Crea una lista che contiene un oggetto `Lion` e un oggetto `Cow` (dall'esercizio precedente). Scorri la lista con un ciclo `for` e chiama il metodo `sound()` su ogni oggetto.\n", + "Creare una lista che contiene un oggetto `Lion` e un oggetto `Cow` (dall'esercizio precedente). Scorrere la lista con un ciclo `for` e chiamare il metodo `sound()` su ogni oggetto.\n", "\n", "### Esercizio 5: Usare `isinstance()`\n", - "Data la lista `elements = [10, \"hello\", Dog(\"Fido\", \"Labrador\"), 50.5]`, scrivi un ciclo `for` che scorra la lista. Se l'elemento è di tipo `Dog`, stampa il suo nome. Altrimenti, stampa un messaggio generico come \"It is not a dog.\".\n", + "Data la lista `elements = [10, \"hello\", Dog(\"Fido\", \"Labrador\"), 50.5]`, scrivere un ciclo `for` che scorra la lista. Se l'elemento è di tipo `Dog`, stampare il suo nome. Altrimenti, stampare un messaggio generico come \"It is not a dog.\".\n", "\n", "### Esercizio 6: Incapsulamento`\n", - "Crea una classe `Product` con un attributo privato `__price`. Il costruttore deve accettare un prezzo iniziale. Aggiungi un metodo `get_price()` per leggere il prezzo e un metodo `set_discount()` che applica uno sconto al prezzo solo se lo sconto è tra 0 e 100." + "Creare una classe `Product` con un attributo privato `__price`. Il costruttore deve accettare un prezzo iniziale. Aggiungere un metodo `get_price()` per leggere il prezzo e un metodo `set_discount()` che applica uno sconto al prezzo solo se lo sconto è tra 0 e 100." ] }, { diff --git a/10_testunit.ipynb b/10_testunit.ipynb index 3110b93..492d741 100755 --- a/10_testunit.ipynb +++ b/10_testunit.ipynb @@ -1,25 +1,27 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "c612dfe5", + "metadata": {}, + "source": [ + "# 🧪 Test Unitari con `unittest` \n", + "\n", + "Il **testing del software** è un processo cruciale che verifica che un programma funzioni come previsto. Non si tratta solo di trovare bug, ma di garantire la qualità, l'affidabilità e la manutenibilità del codice nel tempo. Tra le varie strategie di testing, il **testing unitario** è la più granulare e riesce ad essere eseguita dagli stessi sviluppatori." + ] + }, { "cell_type": "markdown", "id": "024e1f3d", "metadata": {}, "source": [ - "# 🧪 Test Unitari con `unittest` 🧪\n", - "\n", - "---", - "\n", - "## 1. Introduzione ai Test Unitari: Principi e Pratica\n", - "\n", - "Il **testing del software** è un processo cruciale che verifica che un programma funzioni come previsto. Non si tratta solo di trovare bug, ma di garantire la qualità, l'affidabilità e la manutenibilità del codice nel tempo. Tra le varie strategie di testing, il **testing unitario** è la più granulare e riesce ad essere eseguita dagli stessi sviluppatori.\n", - "\n", - "### Cos'è un Test Unitario?\n", + "## Cos'è un Test Unitario?\n", "\n", "Un **test unitario** è una porzione di codice che verifica il comportamento di una singola e isolata \"unità\" del tuo programma. Un'unità può essere una funzione, un metodo di una classe o una singola classe. L'obiettivo è isolare l'unità e assicurarsi che restituisca l'output corretto per un determinato input, in un ambiente controllato.\n", "\n", - "Si può pensare al testing unitario come all'assemblaggio di un'automobile. Prima di testare l'intera vettura, verifichi che ogni singolo componente, come il motore, i freni o il volante, funzioni perfettamente per conto suo. Se un componente è difettoso, lo individui e lo ripari subito, senza dover smontare l'intera macchina in un secondo momento.\n", + "Si può pensare al testing unitario come all'assemblaggio di un'automobile. Prima di testare l'intera vettura, occorre verificare che ogni singolo componente, come il motore, i freni o il volante, funzioni perfettamente per conto suo. Se un componente è difettoso, occorre individuarlo e riparlo subito, senza dover smontare l'intera macchina in un secondo momento.\n", "\n", - "### I Principi del Testing Unitario\n", + "## I Principi del Testing Unitario\n", "\n", "I test unitari efficaci sono guidati da quattro principi chiave, spesso riassunti nell'acronimo **F.I.R.S.T.** (Fast, Isolated, Repeatable, Self-Validating, Timely):\n", "\n", @@ -29,9 +31,9 @@ "- **Self-Validating (Auto-validanti)**: I test non devono richiedere l'intervento manuale per interpretare il risultato. Devono restituire semplicemente un `pass` o un `fail`.\n", "- **Timely (Tempestivi)**: I test dovrebbero essere scritti prima del codice che testano (approccio noto come **Test-Driven Development** o TDD), non dopo. Questo non solo garantisce una buona copertura, ma aiuta a definire l'API e il comportamento atteso del codice.\n", "\n", - "### Il Ruolo di `unittest` in Python\n", + "## Il Ruolo di `unittest` in Python\n", "\n", - "Python include un modulo integrato chiamato **`unittest`**, ispirato a framework di test di altri linguaggi come JUnit. `unittest` fornisce un set completo di strumenti per costruire e gestire i test unitari senza la necessità di installare librerie esterne.\n", + "Python include un modulo integrato chiamato **`unittest`**, ispirato a framework di test di altri linguaggi come JUnit in Java. `unittest` fornisce un set completo di strumenti per costruire e gestire i test unitari senza la necessità di installare librerie esterne.\n", "\n", "Le sue componenti principali sono:\n", "\n", @@ -41,9 +43,7 @@ "\n", "Con `unittest`, si crea una classe di test, si definiscono metodi di test (`test_...`), si usano i metodi di asserzione (`assertEqual`, `assertTrue`, ecc.) per verificare i risultati e si esegue tutto tramite `unittest.main()`.\n", "\n", - "---", - "\n", - "## 2. Metodologia e Pratica di `unittest`\n", + "## Metodologia e Pratica di `unittest`\n", "\n", "Un test unitario con `unittest` segue una struttura ben definita:\n", "\n", @@ -85,13 +85,13 @@ " unittest.main()\n", "```\n", "\n", - "Per eseguire i test, apri il terminale e digita:\n", + "Per eseguire i test, aprire il terminale e digitare:\n", "\n", "```bash\n", "python test_numbers.py\n", "```\n", "\n", - "Se tutti i test passano, vedrai un'uscita simile a `OK`." + "Se tutti i test passano, si vedrà in output `OK`." ] }, { @@ -101,9 +101,9 @@ "source": [ "---", "\n", - "## 3. Esercizi 📝\n", + "## Esercizi 📝\n", "\n", - "Scrivi i test unitari per le seguenti funzioni e classi. Crea un file di test separato per ogni esercizio." + "Scrivere i test unitari per le seguenti funzioni e classi. Creare un file di test separato per ogni esercizio." ] }, { @@ -113,7 +113,7 @@ "source": [ "### Esercizio 1: Funzione `calculate_average`\n", "\n", - "Crea un file `stats.py` con la seguente funzione e scrivi i test per essa in `test_stats.py`.\n", + "Creare un file `stats.py` con la seguente funzione e scrivere i test per essa in `test_stats.py`.\n", "\n", "```python\n", "# stats.py\n", @@ -126,10 +126,10 @@ "\n", "**Istruzioni per i test:**\n", "\n", - "1. Verifica la media di una lista di numeri interi.\n", - "2. Verifica la media di una lista di numeri float.\n", - "3. Verifica che, nel caso di una lista vuota, venga sollevata un'eccezione `ValueError`. Usa `self.assertRaises` per questo scopo.\n", - "4. (Opzionale) Verifica il caso di una lista con un solo elemento." + "1. Verificare la media di una lista di numeri interi.\n", + "2. Verificare la media di una lista di numeri float.\n", + "3. Verificare che, nel caso di una lista vuota, venga sollevata un'eccezione `ValueError`. Usa `self.assertRaises` per questo scopo.\n", + "4. (Opzionale) Verificare il caso di una lista con un solo elemento." ] }, { @@ -141,7 +141,7 @@ "\n", "### Esercizio 2: Classe `User`\n", "\n", - "Crea un file `users.py` con la seguente classe e scrivi i test per i suoi metodi in `test_users.py`.\n", + "Creare un file `users.py` con la seguente classe e scrivere i test per i suoi metodi in `test_users.py`.\n", "\n", "```python\n", "# users.py\n", @@ -162,10 +162,10 @@ "\n", "**Istruzioni per i test:**\n", "\n", - "1. Verifica che, dopo l'inizializzazione, gli attributi `name`, `email` siano corretti e `logged` sia `False`.\n", - "2. Verifica che il metodo `login()` cambi correttamente lo stato di `logged` a `True`.\n", - "3. Verifica che il metodo `logout()` cambi correttamente lo stato di `logged` a `False`.\n", - "4. Verifica che l'inizializzazione della classe sollevi un `ValueError` se `name` o `email` sono stringhe vuote." + "1. Verificare che, dopo l'inizializzazione, gli attributi `name`, `email` siano corretti e `logged` sia `False`.\n", + "2. Verificare che il metodo `login()` cambi correttamente lo stato di `logged` a `True`.\n", + "3. Verificare che il metodo `logout()` cambi correttamente lo stato di `logged` a `False`.\n", + "4. Verificare che l'inizializzazione della classe sollevi un `ValueError` se `name` o `email` sono stringhe vuote." ] }, { @@ -175,7 +175,7 @@ "source": [ "---", "\n", - "## 4. Soluzioni ✅" + "## Soluzioni ✅" ] }, { @@ -185,7 +185,7 @@ "source": [ "### Soluzione Esercizio 1: Test per `calculate_average`\n", "\n", - "Copia questo codice in un file `test_stats.py`." + "Copiare questo codice in un file `test_stats.py`." ] }, { @@ -225,7 +225,7 @@ "source": [ "### Soluzione Esercizio 2: Test per la classe `User`\n", "\n", - "Copia questo codice in un file `test_users.py`." + "Copiare questo codice in un file `test_users.py`." ] }, { diff --git a/11_decorator_closure.ipynb b/11_decorator_closure.ipynb index d7f6569..ec91646 100644 --- a/11_decorator_closure.ipynb +++ b/11_decorator_closure.ipynb @@ -1,12 +1,13 @@ { - "cells": [ - { + "cells": [ + { "cell_type": "markdown", + "id": "c612dfe6", "metadata": {}, "source": [ - "# ⚙️ Decorator e Funzioni Avanzate in Python\n", + "# ⚙️ Decorator e Funzioni Avanzate in Python \n", "\n", - "In questo capitolo approfondiremo alcuni concetti avanzati sulle **funzioni in Python**:\n", + "In questo capitolo approfondiremo alcuni concetti avanzati sulle **funzioni in Python**:\n", "\n", "- Le funzioni come oggetti di prima classe\n", "- Le funzioni annidate\n", @@ -21,7 +22,7 @@ "source": [ "## 🧩 Funzioni come oggetti di prima classe\n", "\n", - "In Python, le funzioni sono considerate **oggetti di prima classe**. Questo significa che puoi trattarle esattamente come qualsiasi altra variabile (come un numero o una lista):\n", + "In Python, le funzioni sono considerate **oggetti di prima classe**. Questo significa che si possono trattare esattamente come qualsiasi altra variabile (come un numero o una lista):\n", "\n", "1. **Possono essere assegnate a variabili** (diventano un alias).\n", "2. **Possono essere passate come argomento** ad altre funzioni (*Higher-Order Functions*).\n", @@ -163,48 +164,6 @@ "say_hi()" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 🎨 Decorator personalizzati\n", - "\n", - "Un **decorator** è una funzione che prende un'altra funzione e ne estende il comportamento **senza modificarne il codice originale**.\n", - "\n", - "Sintassi base:\n", - "```python\n", - "@decorator_name\n", - "def my_function():\n", - " ...\n", - "```\n", - "\n", - "Equivalente a:\n", - "```python\n", - "my_function = decorator_name(my_function)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def log_call(func):\n", - " def wrapper(*args, **kwargs):\n", - " print(f\"Calling {func.__name__}...\")\n", - " result = func(*args, **kwargs)\n", - " print(f\"{func.__name__} finished!\")\n", - " return result\n", - " return wrapper\n", - "\n", - "@log_call\n", - "def say_hi():\n", - " print(\"Hi there!\")\n", - "\n", - "say_hi()" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -246,7 +205,7 @@ "- `@classmethod`\n", "- `@property`\n", "\n", - "Vediamoli in azione 👇" + "Qui vengono mostrati alcuni esempi:" ] }, { @@ -291,13 +250,13 @@ "## Esercizi\n", "\n", "### Esercizio 1: Logging Decorator\n", - "Scrivi un decorator `log_args` che stampi gli argomenti con cui una funzione è stata chiamata.\n", + "Scrivere un decorator `log_args` che stampi gli argomenti con cui una funzione è stata chiamata.\n", "\n", "### Esercizio 2: Timer Decorator\n", - "Crea un decorator `timer` che calcoli il tempo di esecuzione di una funzione.", + "Creare un decorator `timer` che calcoli il tempo di esecuzione di una funzione.", "\n", "### Esercizio 3: Repeat with Parameter\n", - "Crea un decorator parametrico `repeat(n)` che ripeta l’esecuzione della funzione *n* volte.\n", + "Creare un decorator parametrico `repeat(n)` che ripeta l’esecuzione della funzione *n* volte.\n", "\n" ] }, diff --git a/12_progetto.ipynb b/12_progetto.ipynb index 7c2807a..b0015bc 100755 --- a/12_progetto.ipynb +++ b/12_progetto.ipynb @@ -30,20 +30,20 @@ "metadata": {}, "source": [ "---\n", - "## 0. Preparazione del Progetto con Ambienti Virtuali 💻\n", + "## Preparazione del Progetto con Ambienti Virtuali 💻\n", "\n", "Prima di scrivere il codice, occorre creare un ambiente isolato per il nostro progetto. Questo ci assicura che le dipendenze non entrino in conflitto con altri progetti sul tuo sistema.\n", "\n", - "Apri il terminale, naviga nella cartella del progetto ed esegui i seguenti comandi:\n", + "Aprire il terminale, navigare nella cartella del progetto ed eseguire i seguenti comandi:\n", "\n", - "1. **Crea l'ambiente virtuale:**\n", + "1. **Creare l'ambiente virtuale:**\n", " `python3 -m venv venv`\n", "\n", - "2. **Attiva l'ambiente virtuale:**\n", + "2. **Attivare l'ambiente virtuale:**\n", " *Su macOS / Linux:* `source venv/bin/activate`\n", " *Su Windows:* `venv\\Scripts\\activate.bat`\n", "\n", - "3. **Installa la libreria esterna `colorama`:**\n", + "3. **Installare la libreria esterna `colorama`:**\n", " `pip install colorama`\n" ] }, @@ -53,7 +53,7 @@ "metadata": {}, "source": [ "---\n", - "## 1. Struttura del Progetto e Gestione delle Dipendenze 📁\n", + "## Struttura del Progetto e Gestione delle Dipendenze 📁\n", "\n", "Per un'organizzazione chiara e professionale, il progetto è suddiviso in più file. Questo rende il codice più facile da leggere, testare e mantenere.\n", "\n", @@ -79,7 +79,7 @@ "colorama==0.4.6\n", "```\n", "\n", - "Puoi installare tutte le dipendenze usando pip:\n", + "Si possono installare tutte le dipendenze usando pip:\n", "\n", "```bash\n", "pip install -r requirements.txt\n", @@ -92,9 +92,9 @@ "metadata": {}, "source": [ "---\n", - "## 2. Implementazione del Codice 💻\n", + "## Implementazione del Codice 💻\n", "\n", - "Di seguito trovi il codice suddiviso nei rispettivi file. **Esegui ogni cella in ordine per creare i file del progetto prima di eseguire `main.py` o i test.**" + "Di seguito il codice suddiviso nei rispettivi file. **Eseguire ogni cella in ordine per creare i file del progetto prima di eseguire `main.py` o i test.**" ] }, { @@ -417,9 +417,9 @@ "metadata": {}, "source": [ "---\n", - "## 3. Esecuzione del Progetto e Simulazione 🚀\n", + "## Esecuzione del Progetto e Simulazione 🚀\n", "\n", - "Dopo aver eseguito le celle precedenti (il che creerà i file `.py`), puoi avviare il programma principale e interagire con esso. Esegui la cella seguente per avviare il menu del programma." + "Dopo aver eseguito le celle precedenti (il che creerà i file `.py`), si può avviare il programma principale e interagire con esso. Eseguire la cella seguente per avviare il menu del programma." ] }, { @@ -438,13 +438,13 @@ "metadata": {}, "source": [ "---\n", - "## 4. Test Unitari con `unittest` 🧪\n", + "## Test Unitari con `unittest` 🧪\n", "\n", "Ora che il progetto è stato implementato, è fondamentale testarne le funzionalità in modo automatico. Aggiungeremo una cartella `tests` alla struttura del progetto, dove scriveremo i nostri test unitari per la classe `GestoreInventario`.\n", "\n", "### Preparazione della cartella di test\n", "\n", - "Esegui la cella sottostante per creare la cartella `tests`." + "Eseguire la cella sottostante per creare la cartella `tests`." ] }, { @@ -552,7 +552,7 @@ "source": [ "### Esecuzione dei Test Unitari\n", "\n", - "Esegui la cella seguente per avviare i test unitari. Se tutto il codice è stato scritto correttamente, dovresti vedere l'output dei test che confermano il corretto funzionamento del tuo programma." + "Eseguire la cella seguente per avviare i test unitari. Se tutto il codice è stato scritto correttamente, si dovrebbe vedere l'output dei test che confermano il corretto funzionamento del programma." ] }, {