Skip to content

Commit 4042f71

Browse files
committed
version 2.0
1 parent 9efb410 commit 4042f71

File tree

5 files changed

+464
-141
lines changed

5 files changed

+464
-141
lines changed

00_sommario_corso.ipynb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"8. [Librerie e Ambienti Virtuali](08_librerie.ipynb)\n",
3838
"9. [Programmazione Orientata agli Oggetti](09_oop.ipynb)\n",
3939
"10. [Test Unitari](10_testunit.ipynb)\n",
40-
"11. [Progetto conclusivo](11_progetto.ipynb)\n",
40+
"11. [Decorator, closure e funzioni avanzate](11_decorator_closure.ipynb)\n",
41+
"12. [Progetto conclusivo](12_progetto.ipynb)\n",
4142
"\n",
4243
"## 🎯 Obiettivi del Corso\n",
4344
"- Imparare la sintassi base di Python.\n",
@@ -52,6 +53,7 @@
5253
"- Librerie aggiuntive e Ambienti Virtuali, come usare librerie aggiuntive e come abilitare ambienti virtuali.\n",
5354
"- Programmazione Orientata agli Oggetti, concetti base.\n",
5455
"- Progettare test unitari per i programmi.\n",
56+
"- Decorator, clojure e funzioni avanzate.\n",
5557
"- Progetto conclusivo, realizzare una semplica applicazione applicando i vari concetti appresi.\n",
5658
"- Appendice. Informazioni aggiuntive.\n",
5759
"\n",

11_decorator_closure.ipynb

Lines changed: 346 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,346 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# ⚙️ Decorator e Funzioni Avanzate in Python\n",
8+
"\n",
9+
"In questo capitolo approfondiremo alcuni concetti avanzati sulle **funzioni in Python**:\n",
10+
"\n",
11+
"- Le funzioni come oggetti di prima classe\n",
12+
"- Le funzioni annidate\n",
13+
"- Le *closure*\n",
14+
"- I *decorator* personalizzati e integrati\n",
15+
"\n"
16+
]
17+
},
18+
{
19+
"cell_type": "markdown",
20+
"metadata": {},
21+
"source": [
22+
"## 🧩 Funzioni come oggetti di prima classe\n",
23+
"\n",
24+
"In Python, le funzioni possono essere trattate come **oggetti**, cioè:\n",
25+
"- possono essere passate come argomento,\n",
26+
"- ritornate da altre funzioni,\n",
27+
"- assegnate a variabili."
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"def greet(name):\n",
37+
" return f\"Hello, {name}!\"\n",
38+
"\n",
39+
"# Assigning the function to a variable\n",
40+
"say_hello = greet\n",
41+
"\n",
42+
"print(say_hello(\"Pythonista\"))"
43+
]
44+
},
45+
{
46+
"cell_type": "markdown",
47+
"metadata": {},
48+
"source": [
49+
"## 🧱 Funzioni annidate (Nested Functions)\n",
50+
"\n",
51+
"Una funzione può essere **definita all'interno** di un'altra funzione. Questo è utile per incapsulare logica o creare funzioni di supporto locali."
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": null,
57+
"metadata": {},
58+
"outputs": [],
59+
"source": [
60+
"def outer_function():\n",
61+
" def inner_function():\n",
62+
" print(\"Inner function executed!\")\n",
63+
" \n",
64+
" print(\"Outer function running...\")\n",
65+
" inner_function()\n",
66+
"\n",
67+
"outer_function()"
68+
]
69+
},
70+
{
71+
"cell_type": "markdown",
72+
"metadata": {},
73+
"source": [
74+
"## 🌀 Closure\n",
75+
"\n",
76+
"Una **closure** è una funzione che ricorda i valori delle variabili dell’ambiente in cui è stata creata, anche dopo che quell’ambiente è stato distrutto."
77+
]
78+
},
79+
{
80+
"cell_type": "code",
81+
"execution_count": null,
82+
"metadata": {},
83+
"outputs": [],
84+
"source": [
85+
"def make_multiplier(x):\n",
86+
" def multiplier(y):\n",
87+
" return x * y # remembers the value of x\n",
88+
" return multiplier\n",
89+
"\n",
90+
"times3 = make_multiplier(3)\n",
91+
"print(times3(5)) # 15"
92+
]
93+
},
94+
{
95+
"cell_type": "markdown",
96+
"metadata": {},
97+
"source": [
98+
"## 🎨 Decorator personalizzati\n",
99+
"\n",
100+
"Un **decorator** è una funzione che prende un'altra funzione e ne estende il comportamento **senza modificarne il codice originale**.\n",
101+
"\n",
102+
"Sintassi base:\n",
103+
"```python\n",
104+
"@decorator_name\n",
105+
"def my_function():\n",
106+
" ...\n",
107+
"```\n",
108+
"\n",
109+
"Equivalente a:\n",
110+
"```python\n",
111+
"my_function = decorator_name(my_function)\n",
112+
"```"
113+
]
114+
},
115+
{
116+
"cell_type": "code",
117+
"execution_count": null,
118+
"metadata": {},
119+
"outputs": [],
120+
"source": [
121+
"def log_call(func):\n",
122+
" def wrapper(*args, **kwargs):\n",
123+
" print(f\"Calling {func.__name__}...\")\n",
124+
" result = func(*args, **kwargs)\n",
125+
" print(f\"{func.__name__} finished!\")\n",
126+
" return result\n",
127+
" return wrapper\n",
128+
"\n",
129+
"@log_call\n",
130+
"def say_hi():\n",
131+
" print(\"Hi there!\")\n",
132+
"\n",
133+
"say_hi()"
134+
]
135+
},
136+
{
137+
"cell_type": "markdown",
138+
"metadata": {},
139+
"source": [
140+
"## ⚙️ Decorator con argomenti\n",
141+
"\n",
142+
"Un decorator può anche accettare **parametri**, grazie a un ulteriore livello di funzioni annidate."
143+
]
144+
},
145+
{
146+
"cell_type": "code",
147+
"execution_count": null,
148+
"metadata": {},
149+
"outputs": [],
150+
"source": [
151+
"def repeat(n):\n",
152+
" def decorator(func):\n",
153+
" def wrapper(*args, **kwargs):\n",
154+
" for _ in range(n):\n",
155+
" func(*args, **kwargs)\n",
156+
" return wrapper\n",
157+
" return decorator\n",
158+
"\n",
159+
"@repeat(3)\n",
160+
"def greet():\n",
161+
" print(\"Hello!\")\n",
162+
"\n",
163+
"greet()"
164+
]
165+
},
166+
{
167+
"cell_type": "markdown",
168+
"metadata": {},
169+
"source": [
170+
"## 🧰 Decorator integrati in Python\n",
171+
"\n",
172+
"Python fornisce alcuni decorator integrati:\n",
173+
"- `@staticmethod`\n",
174+
"- `@classmethod`\n",
175+
"- `@property`\n",
176+
"\n",
177+
"Vediamoli in azione 👇"
178+
]
179+
},
180+
{
181+
"cell_type": "code",
182+
"execution_count": null,
183+
"metadata": {},
184+
"outputs": [],
185+
"source": [
186+
"class Circle:\n",
187+
" def __init__(self, radius):\n",
188+
" self._radius = radius\n",
189+
"\n",
190+
" @property\n",
191+
" def radius(self):\n",
192+
" return self._radius\n",
193+
"\n",
194+
" @radius.setter\n",
195+
" def radius(self, value):\n",
196+
" if value <= 0:\n",
197+
" raise ValueError(\"Radius must be positive\")\n",
198+
" self._radius = value\n",
199+
"\n",
200+
" @staticmethod\n",
201+
" def info():\n",
202+
" print(\"A circle is a round shape.\")\n",
203+
"\n",
204+
" @classmethod\n",
205+
" def unit_circle(cls):\n",
206+
" return cls(1)\n",
207+
"\n",
208+
"c = Circle(5)\n",
209+
"print(c.radius)\n",
210+
"Circle.info()\n",
211+
"unit = Circle.unit_circle()\n",
212+
"print(unit.radius)"
213+
]
214+
},
215+
{
216+
"cell_type": "markdown",
217+
"metadata": {},
218+
"source": [
219+
"## Esercizi\n",
220+
"\n",
221+
"### Esercizio 1: Logging Decorator\n",
222+
"Scrivi un decorator `log_args` che stampi gli argomenti con cui una funzione è stata chiamata.\n",
223+
"\n",
224+
"### Esercizio 2: Timer Decorator\n",
225+
"Crea un decorator `timer` che calcoli il tempo di esecuzione di una funzione.",
226+
"\n",
227+
"### Esercizio 3: Repeat with Parameter\n",
228+
"Crea un decorator parametrico `repeat(n)` che ripeta l’esecuzione della funzione *n* volte.\n",
229+
"\n"
230+
]
231+
},
232+
{
233+
"cell_type": "markdown",
234+
"metadata": {},
235+
"source": [
236+
"## Soluzioni\n",
237+
"\n",
238+
"### Soluzione Esercizio 1"
239+
]
240+
},
241+
{
242+
"cell_type": "code",
243+
"execution_count": null,
244+
"metadata": {},
245+
"outputs": [],
246+
"source": [
247+
"# Logging Decorator\n",
248+
"def log_args(func):\n",
249+
" def wrapper(*args, **kwargs):\n",
250+
" print(f\"Arguments: {args}, Keyword Arguments: {kwargs}\")\n",
251+
" return func(*args, **kwargs)\n",
252+
" return wrapper\n",
253+
"\n",
254+
"@log_args\n",
255+
"def add(a, b):\n",
256+
" return a + b\n",
257+
"\n",
258+
"print(add(5, 3))"
259+
]
260+
},
261+
{
262+
"cell_type": "markdown",
263+
"metadata": {},
264+
"source": [
265+
"### Soluzione Esercizio 2"
266+
]
267+
},
268+
{
269+
"cell_type": "code",
270+
"execution_count": null,
271+
"metadata": {},
272+
"outputs": [],
273+
"source": [
274+
"# Timer Decorator\n",
275+
"import time\n",
276+
"\n",
277+
"def timer(func):\n",
278+
" def wrapper(*args, **kwargs):\n",
279+
" start = time.time()\n",
280+
" result = func(*args, **kwargs)\n",
281+
" end = time.time()\n",
282+
" print(f\"Execution time: {end - start:.4f} seconds\")\n",
283+
" return result\n",
284+
" return wrapper\n",
285+
"\n",
286+
"@timer\n",
287+
"def slow_function():\n",
288+
" time.sleep(1)\n",
289+
" print(\"Finished!\")\n",
290+
"\n",
291+
"slow_function()"
292+
]
293+
},
294+
{
295+
"cell_type": "markdown",
296+
"metadata": {},
297+
"source": [
298+
"### Soluzione Esercizio 3"
299+
]
300+
},
301+
{
302+
"cell_type": "code",
303+
"execution_count": null,
304+
"metadata": {},
305+
"outputs": [],
306+
"source": [
307+
"# Repeat Decorator with parameter\n",
308+
"def repeat(n):\n",
309+
" def decorator(func):\n",
310+
" def wrapper(*args, **kwargs):\n",
311+
" for i in range(n):\n",
312+
" print(f\"Execution {i+1}/{n}\")\n",
313+
" func(*args, **kwargs)\n",
314+
" return wrapper\n",
315+
" return decorator\n",
316+
"\n",
317+
"@repeat(3)\n",
318+
"def say_hi():\n",
319+
" print(\"Hi!\")\n",
320+
"\n",
321+
"say_hi()"
322+
]
323+
},
324+
{
325+
"cell_type": "markdown",
326+
"id": "footer",
327+
"metadata": {},
328+
"source": [
329+
"&copy; 2025 Hanamai. All rights reserved. | Built with precision for real-time data streaming excellence."
330+
]
331+
}
332+
],
333+
"metadata": {
334+
"kernelspec": {
335+
"display_name": "Python 3",
336+
"language": "python",
337+
"name": "python3"
338+
},
339+
"language_info": {
340+
"name": "python",
341+
"version": "3.11"
342+
}
343+
},
344+
"nbformat": 4,
345+
"nbformat_minor": 5
346+
}

0 commit comments

Comments
 (0)