Skip to content

Commit 9f7582b

Browse files
committed
added operator isinstance in section 09
1 parent f0d7601 commit 9f7582b

File tree

1 file changed

+103
-11
lines changed

1 file changed

+103
-11
lines changed

09_oop.ipynb

Lines changed: 103 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
"\n",
170170
"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",
171171
"- Un singolo underscore (`_`) suggerisce che l'attributo è **protetto** (`_attributo_protetto`).\n",
172-
"- Un doppio underscore (`__`) rende l'attributo **privato** (`__attributo_privato`) usando una tecnica chiamata `name mangling`.\n"
172+
"- Un doppio underscore (`__`) rende l'attributo **privato** (`__attributo_privato`) usando una tecnica chiamata `name mangling`."
173173
]
174174
},
175175
{
@@ -189,21 +189,83 @@
189189
" self.__saldo += importo\n",
190190
" print(f\"Deposito di {importo} euro. Nuovo saldo: {self.__saldo}\")\n",
191191
"\n",
192-
" def get_saldo(self):\n",
193-
" # Metodo pubblico per accedere in modo controllato al saldo\n",
194-
" return self.__saldo\n",
192+
" def get_saldo(self, pin):\n",
193+
" # Metodo pubblico per accedere in modo controllato al saldo, magari con un PIN\n",
194+
" if pin == \"1234\": # Esempio semplice\n",
195+
" return self.__saldo\n",
196+
" else:\n",
197+
" return \"PIN errato!\"\n",
195198
"\n",
196199
"conto = ContoBancario(100)\n",
197200
"conto.deposita(50)\n",
198201
"\n",
199202
"# Tentare di accedere direttamente fallirà (genera un errore)\n",
200203
"# print(conto.__saldo) # Questo causerebbe un AttributeError\n",
201-
"print(f\"Il saldo tramite il metodo get_saldo è: {conto.get_saldo()}\")"
204+
"print(f\"Il saldo tramite il metodo get_saldo è: {conto.get_saldo('1234')}\")"
205+
]
206+
},
207+
{
208+
"cell_type": "markdown",
209+
"metadata": {},
210+
"source": [
211+
"---"
212+
]
213+
},
214+
{
215+
"cell_type": "markdown",
216+
"id": "b73c734e",
217+
"metadata": {},
218+
"source": [
219+
"## 5. L'operatore `isinstance()`: Controllo del Tipo 🤔\n",
220+
"\n",
221+
"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",
222+
"\n",
223+
"**Sintassi:**\n",
224+
"```python\n",
225+
"isinstance(oggetto, classe)\n",
226+
"```\n",
227+
"- `oggetto`: L'istanza che vuoi verificare.\n",
228+
"- `classe`: La classe (o una tupla di classi) rispetto a cui vuoi fare la verifica.\n",
229+
"\n",
230+
"La funzione ritorna `True` se l'oggetto è del tipo specificato (o di una delle sue sottoclassi), altrimenti `False`.\n",
231+
"\n",
232+
"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",
233+
"\n",
234+
"- Quando hai bisogno di agire in modo diverso in base al **tipo esatto** di un oggetto.\n",
235+
"- Per verificare che un oggetto sia conforme a un'**interfaccia** o a una classe astratta specifica.\n",
236+
"- Per garantire la compatibilità con librerie esterne che si aspettano tipi specifici.\n",
237+
"\n",
238+
"È importante usare `isinstance()` con parsimonia per evitare una **proliferazione eccessiva** di controlli sul tipo, che può rendere il codice rigido e meno `pythonico`. La flessibilità del polimorfismo è spesso la soluzione migliore, ma `isinstance()` è lo strumento giusto quando serve un controllo più preciso sul tipo di dato in gioco.\n",
239+
"\n",
240+
"**Esempio:**\n",
241+
"```python\n",
242+
"class Veicolo:\n",
243+
" pass\n",
244+
"\n",
245+
"class Auto(Veicolo):\n",
246+
" pass\n",
247+
"\n",
248+
"mia_auto = Auto()\n",
249+
"mia_moto = Veicolo()\n",
250+
"\n",
251+
"# Verifica se mia_auto è un'istanza della classe Auto\n",
252+
"print(isinstance(mia_auto, Auto)) # Output: True\n",
253+
"\n",
254+
"# Verifica se mia_auto è un'istanza della classe Veicolo\n",
255+
"# Ritorna True perché Auto è una sottoclasse di Veicolo\n",
256+
"print(isinstance(mia_auto, Veicolo)) # Output: True\n",
257+
"\n",
258+
"# Verifica se un oggetto è di uno dei tipi specificati\n",
259+
"print(isinstance(mia_auto, (int, str, Auto))) # Output: True\n",
260+
"\n",
261+
"# Verifica se una stringa è un'istanza di Auto\n",
262+
"print(isinstance(\"testo\", Auto)) # Output: False\n",
263+
"```"
202264
]
203265
},
204266
{
205267
"cell_type": "markdown",
206-
"id": "5f5817ea",
268+
"id": "c5de76d0",
207269
"metadata": {},
208270
"source": [
209271
"---"
@@ -214,7 +276,7 @@
214276
"id": "c5de76d0",
215277
"metadata": {},
216278
"source": [
217-
"## 5. Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n",
279+
"## 6. Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n",
218280
"\n",
219281
"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."
220282
]
@@ -258,7 +320,7 @@
258320
"id": "f92678a7",
259321
"metadata": {},
260322
"source": [
261-
"## 6. Classi Astratte 📝\n",
323+
"## 7. Classi Astratte 📝\n",
262324
"\n",
263325
"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",
264326
"\n",
@@ -318,7 +380,10 @@
318380
"### Esercizio 4: Polimorfismo in azione (Concetti Avanzati)\n",
319381
"Crea una lista che contiene un oggetto `Leone` e un oggetto `Mucca` (dall'esercizio precedente). Scorri la lista con un ciclo `for` e chiama il metodo `verso()` su ogni oggetto.\n",
320382
"\n",
321-
"### Esercizio 5: Incapsulamento con un `Prodotto` (Concetti Avanzati)\n",
383+
"### Esercizio 5: Usare `isinstance()`\n",
384+
"Data la lista `elementi = [10, \"ciao\", Cane(\"Fido\", \"Labrador\"), 50.5]`, scrivi un ciclo `for` che scorra la lista. Se l'elemento è di tipo `Cane`, stampa il suo nome. Altrimenti, stampa un messaggio generico come \"Non è un cane.\".\n",
385+
"\n",
386+
"### Esercizio 6: Incapsulamento con un `Prodotto` (Concetti Avanzati)\n",
322387
"Crea una classe `Prodotto` con un attributo privato `__prezzo`. Il costruttore deve accettare un prezzo iniziale. Aggiungi un metodo `get_prezzo()` per leggere il prezzo e un metodo `set_sconto()` che applica uno sconto al prezzo solo se lo sconto è tra 0 e 100."
323388
]
324389
},
@@ -451,12 +516,39 @@
451516
" animale.verso()"
452517
]
453518
},
519+
{
520+
"cell_type": "markdown",
521+
"metadata": {},
522+
"source": [
523+
"### Soluzione Esercizio 5: Usare `isinstance()`"
524+
]
525+
},
526+
{
527+
"cell_type": "code",
528+
"execution_count": null,
529+
"metadata": {},
530+
"outputs": [],
531+
"source": [
532+
"class Cane:\n",
533+
" def __init__(self, nome, razza):\n",
534+
" self.nome = nome\n",
535+
" self.razza = razza\n",
536+
"\n",
537+
"elementi = [10, \"ciao\", Cane(\"Fido\", \"Labrador\"), 50.5]\n",
538+
"\n",
539+
"for elemento in elementi:\n",
540+
" if isinstance(elemento, Cane):\n",
541+
" print(f\"Trovato un cane! Si chiama {elemento.nome}.\")\n",
542+
" else:\n",
543+
" print(f\"Non è un cane. È un {type(elemento)}.\")"
544+
]
545+
},
454546
{
455547
"cell_type": "markdown",
456548
"id": "7b95316c",
457549
"metadata": {},
458550
"source": [
459-
"### Soluzione Esercizio 5: Incapsulamento con un `Prodotto`"
551+
"### Soluzione Esercizio 6: Incapsulamento con un `Prodotto`"
460552
]
461553
},
462554
{
@@ -508,4 +600,4 @@
508600
},
509601
"nbformat": 4,
510602
"nbformat_minor": 5
511-
}
603+
}

0 commit comments

Comments
 (0)