You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"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",
171
171
"- 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`."
173
173
]
174
174
},
175
175
{
@@ -189,21 +189,83 @@
189
189
" self.__saldo += importo\n",
190
190
" print(f\"Deposito di {importo} euro. Nuovo saldo: {self.__saldo}\")\n",
191
191
"\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",
195
198
"\n",
196
199
"conto = ContoBancario(100)\n",
197
200
"conto.deposita(50)\n",
198
201
"\n",
199
202
"# Tentare di accedere direttamente fallirà (genera un errore)\n",
200
203
"# 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",
"## 5. Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n",
279
+
"## 6. Polimorfismo: Tante Forme, Stesso Comportamento 🎭\n",
218
280
"\n",
219
281
"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."
220
282
]
@@ -258,7 +320,7 @@
258
320
"id": "f92678a7",
259
321
"metadata": {},
260
322
"source": [
261
-
"## 6. Classi Astratte 📝\n",
323
+
"## 7. Classi Astratte 📝\n",
262
324
"\n",
263
325
"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",
264
326
"\n",
@@ -318,7 +380,10 @@
318
380
"### Esercizio 4: Polimorfismo in azione (Concetti Avanzati)\n",
319
381
"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",
320
382
"\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",
322
387
"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."
0 commit comments