Skip to content

Commit 3d0d1dc

Browse files
authored
Update 16-writing-functions.md
finito
1 parent 842f55e commit 3d0d1dc

1 file changed

Lines changed: 55 additions & 116 deletions

File tree

episodes/16-writing-functions.md

Lines changed: 55 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ exercises: 15
77

88
::::::::::::::::::::::::::::::::::::::: objectives
99

10-
- Spiegare e identificare la differenza tra definizione di funzione e chiamata di
11-
funzione.
12-
- Scrivete una funzione che prende un piccolo numero fisso di argomenti e produce un
13-
unico risultato.
10+
- Spiegare e identificare la differenza tra definizione di funzione e chiamata di funzione.
11+
- Scrivere una funzione che prenda un piccolo numero fisso di argomenti e produca un unico risultato.
1412

1513
::::::::::::::::::::::::::::::::::::::::::::::::::
1614

@@ -22,26 +20,25 @@ exercises: 15
2220

2321
## Scomporre i programmi in funzioni per renderli più comprensibili.
2422

25-
- Gli esseri umani possono tenere nella memoria di lavoro solo pochi elementi alla
26-
volta.
27-
- Comprendere idee più grandi/più complicate comprendendo e combinando pezzi.
23+
- Gli esseri umani possono tenere nella memoria di lavoro solo pochi elementi alla volta.
24+
- Comprendiamo idee più grandi/più complesse combinando pezzi.
2825
- Componenti di una macchina.
2926
- Lemmi per la dimostrazione di teoremi.
30-
- Le funzioni hanno lo stesso scopo nei programmi.
31-
- *Incapsula* la complessità in modo da poterla trattare come un'unica "cosa".
32-
- consente anche il *riutilizzo*.
27+
- Le funzioni hanno lo stesso scopo nei programmi:
28+
- *Incapsulare* a complessità in modo da poterla trattare come ununica "cosa".
29+
- Consentono anche il *riutilizzo*.
3330
- Scrivere una volta, usare molte volte.
3431

3532
## Definire una funzione usando `def` con un nome, dei parametri e un blocco di codice.
3633

3734
- Iniziare la definizione di una nuova funzione con `def`.
38-
- Seguito dal nome della funzione.
35+
- Seguire con il nome della funzione.
3936
- Deve rispettare le stesse regole dei nomi delle variabili.
40-
- Allora *parametri* tra parentesi.
41-
- parentesi vuote se la funzione non riceve input.
37+
- Poi i *parametri* tra parentesi.
38+
- Parentesi vuote se la funzione non riceve input.
4239
- Ne parleremo in dettaglio tra poco.
4340
- Poi i due punti.
44-
- Poi un blocco di codice rientrato.
41+
- nfine un blocco di codice rientrato.
4542

4643
```python
4744
def print_greeting():
@@ -50,11 +47,11 @@ def print_greeting():
5047
print('Right?')
5148
```
5249

53-
## Definire una funzione non la fa funzionare.
50+
## Definire una funzione non la fa eseguire.
5451

55-
- Definire una funzione non la fa funzionare.
52+
- Definire una funzione non la fa eseguire.
5653
- Come assegnare un valore a una variabile.
57-
- Deve chiamare la funzione per eseguire il codice che contiene.
54+
- Si deve chiamare la funzione per eseguire il codice che contiene.
5855

5956
```python
6057
print_greeting()
@@ -86,10 +83,7 @@ print_date(1871, 3, 19)
8683
1871/3/19
8784
```
8885

89-
Oppure, possiamo dare un nome agli argomenti quando chiamiamo la funzione, il che ci
90-
permette di specificarli in qualsiasi ordine e aggiunge chiarezza al sito di chiamata;
91-
altrimenti, mentre si legge il codice, si potrebbe dimenticare se il secondo argomento è
92-
il mese o il giorno, ad esempio.
86+
Oppure, possiamo dare un nome agli argomenti quando chiamiamo la funzione, il che ci permette di specificarli in qualsiasi ordine e aggiunge chiarezza al sito di chiamata; altrimenti, mentre si legge il codice, si potrebbe dimenticare se il secondo argomento è il mese o il giorno, ad esempio.
9387

9488
```python
9589
print_date(month=3, day=19, year=1871)
@@ -99,16 +93,15 @@ print_date(month=3, day=19, year=1871)
9993
1871/3/19
10094
```
10195

102-
- Via [Twitter](https://twitter.com/minisciencegirl/status/693486088963272705): `()`
103-
contiene gli ingredienti della funzione mentre il corpo contiene la ricetta.
96+
- Via [Twitter](https://twitter.com/minisciencegirl/status/693486088963272705): `()` contiene gli ingredienti della funzione mentre il corpo contiene la ricetta.
10497

10598
## Le funzioni possono restituire un risultato al loro chiamante usando `return`.
10699

107100
- Usare `return ...` per restituire un valore al chiamante.
108101
- Può verificarsi in qualsiasi punto della funzione.
109-
- Ma le funzioni sono più facili da capire se si presenta `return`:
102+
- Ma le funzioni sono più facili da capire se si usa `return`:
110103
- All'inizio per gestire casi speciali.
111-
- Alla fine, con un risultato finale.
104+
- Alla fine, con il risultato finale.
112105

113106
```python
114107
def average(values):
@@ -201,10 +194,7 @@ print('calling', report, 22.5)
201194
calling <function report at 0x7fd128ff1bf8> 22.5
202195
```
203196

204-
Una chiamata di funzione ha sempre bisogno di parentesi, altrimenti si ottiene
205-
l'indirizzo di memoria dell'oggetto funzione. Quindi, se volessimo chiamare la funzione
206-
denominata report e assegnarle il valore 22,5, potremmo chiamare la funzione nel modo
207-
seguente
197+
Una chiamata di funzione ha sempre bisogno delle parentesi, altrimenti si ottiene il riferimento all’oggetto funzione. Se volessimo chiamare la funzione report passando il valore 22,5, potremmo scrivere:
208198

209199
```python
210200
print("calling")
@@ -234,8 +224,7 @@ pressure is 22.5
234224
print(time_string)
235225
```
236226

237-
2. Dopo aver risolto il problema di cui sopra, spiegare perché eseguire questo esempio
238-
di codice:
227+
2. Dopo aver risolto il problema di cui sopra, spiegate perché eseguire questo esempio:
239228

240229
```python
241230
result = print_time(11, 37, 59)
@@ -249,24 +238,17 @@ dà questo risultato:
249238
result of call is: None
250239
```
251240

252-
3. Perché il risultato della chiamata è `None`?
241+
3. Perché il risultato è `None`?
253242

254243
::::::::::::::: solution
255244

256245
## Soluzione
257246

258-
1. Il problema dell'esempio è che la funzione `print_time()` viene definita *dopo* che
259-
la funzione è stata chiamata. Python non sa come risolvere il nome `print_time`,
260-
poiché non è ancora stato definito, e solleverà un `NameError`, ad esempio
261-
`NameError: name 'print_time' is not defined`
247+
1. Il problema dell'esempio è che la funzione `print_time()` viene definita *dopo* che la funzione è stata chiamata. Python non sa come risolvere il nome `print_time`, poiché non è ancora stato definito, e solleverà un `NameError`, ad esempio NameError: name 'print_time' is not defined`
262248

263-
2. La prima riga di output `11:37:59` è stampata dalla prima riga di codice, `result =
264-
print_time(11, 37, 59)` che lega il valore restituito dall'invocazione `print_time`
265-
alla variabile `result`. La seconda riga proviene dalla seconda chiamata di stampa
266-
per stampare il contenuto della variabile `result`.
249+
2. La prima riga di output `11:37:59` è stampata dalla prima riga di codice, `result = print_time(11, 37, 59)` che lega il valore restituito dall'invocazione `print_time` alla variabile `result`. La seconda riga proviene dalla seconda chiamata di stampa per stampare il contenuto della variabile `result`.
267250

268-
3. `print_time()` non restituisce esplicitamente `return` un valore, quindi restituisce
269-
automaticamente `None`.
251+
3. `print_time()` non restituisce esplicitamente `return` un valore, quindi restituisce automaticamente `None`.
270252

271253
:::::::::::::::::::::::::
272254

@@ -276,9 +258,7 @@ dà questo risultato:
276258

277259
## Incapsulamento
278260

279-
Compilate gli spazi vuoti per creare una funzione che prenda come argomento un singolo
280-
nome di file, carichi i dati nel file denominato dall'argomento e restituisca il valore
281-
minimo in quei dati.
261+
Compilate gli spazi vuoti per creare una funzione che prenda come argomento un singolo nome di file, carichi i dati nel file indicato e restituisca il valore minimo in quei dati.
282262

283263
```python
284264
import pandas as pd
@@ -308,9 +288,7 @@ def min_in_data(filename):
308288

309289
## Trovare il primo
310290

311-
Riempite gli spazi vuoti per creare una funzione che prenda come argomento un elenco di
312-
numeri e restituisca il primo valore negativo dell'elenco. Cosa fa la funzione se
313-
l'elenco è vuoto? E se l'elenco non contiene numeri negativi?
291+
Riempite gli spazi vuoti per creare una funzione che prenda come argomento un elenco di numeri e restituisca il primo valore negativo dell’elenco. Cosa fa la funzione se l’elenco è vuoto? E se l’elenco non contiene numeri negativi?
314292

315293
```python
316294
def first_negative(values):
@@ -358,8 +336,7 @@ def print_date(year, month, day):
358336
print(joined)
359337
```
360338

361-
Abbiamo visto che possiamo chiamare la funzione usando *argomenti con nome*, in questo
362-
modo:
339+
Abbiamo visto che possiamo chiamare la funzione usando *argomenti con nome*, in questo modo:
363340

364341
```python
365342
print_date(day=1, month=2, year=2003)
@@ -374,39 +351,31 @@ print_date(day=1, month=2, year=2003)
374351
## Soluzione
375352

376353
1. `2003/2/1`
377-
2. Abbiamo visto esempi di utilizzo di *argomenti con nome* quando si lavora con la
378-
libreria pandas. Per esempio, quando si legge un set di dati usando `data =
379-
pd.read_csv('data/gapminder_gdp_europe.csv', index_col='country')`, l'ultimo
354+
2. Abbiamo visto esempi di utilizzo di *argomenti con nome* quando lavoravamo con la libreria pandas. Per esempio, quando si legge un set di dati usando `data = pd.read_csv('data/gapminder_gdp_europe.csv', index_col='country')`, l'ultimo
380355
argomento `index_col` è un argomento con nome.
381356
3. L'uso di argomenti con nome può rendere il codice più leggibile, poiché dalla
382-
chiamata di funzione si può vedere quale nome hanno i diversi argomenti all'interno
383-
della funzione. Inoltre, può ridurre le possibilità di passare gli argomenti
384-
nell'ordine sbagliato, poiché utilizzando argomenti con nome l'ordine non ha
385-
importanza.
357+
chiamata di funzione si può vedere quale nome hanno i diversi argomenti all'interno della funzione. Inoltre, può ridurre le possibilità di passare gli argomenti nell'ordine sbagliato, poiché utilizzando argomenti con nome l'ordine non ha importanza.
386358

387359
:::::::::::::::::::::::::
388360

389361
::::::::::::::::::::::::::::::::::::::::::::::::::
390362

391363
::::::::::::::::::::::::::::::::::::::: challenge
392364

393-
## Incapsulamento di un blocco Se/Stampa
394-
395-
Il codice seguente viene eseguito su una stampante di etichette per uova di gallina. Una
396-
bilancia digitale comunicherà al computer la massa di un uovo di gallina (in grammi) e
397-
il computer stamperà un'etichetta.
365+
## Incapsulamento di un blocco If/Stampa
366+
Il codice seguente viene eseguito su una stampante di etichette per uova di gallina. Una bilancia digitale comunica al computer la massa di un uovo (in grammi) e il computer stampa un’etichetta.
398367

399368
```python
400369
import random
401370
for i in range(10):
402371

403-
# simulating the mass of a chicken egg
404-
# the (random) mass will be 70 +/- 20 grams
372+
# simulazione della massa di un uovo di gallina
373+
# la massa (casuale) sarà di 70 ± 20 grammi
405374
mass = 70 + 20.0 * (2.0 * random.random() - 1.0)
406375

407376
print(mass)
408377

409-
# egg sizing machinery prints a label
378+
# il sistema di classificazione stampa un'etichetta
410379
if mass >= 85:
411380
print("jumbo")
412381
elif mass >= 70:
@@ -426,8 +395,8 @@ Rivedendo il programma per utilizzare la funzione si otterrebbe questo:
426395
import random
427396
for i in range(10):
428397

429-
# simulating the mass of a chicken egg
430-
# the (random) mass will be 70 +/- 20 grams
398+
# simulazione della massa di un uovo di gallina
399+
# la massa (casuale) sarà di 70 ± 20 grammi
431400
mass = 70 + 20.0 * (2.0 * random.random() - 1.0)
432401

433402
print(mass, get_egg_label(mass))
@@ -438,18 +407,15 @@ for i in range(10):
438407
programma rivisto sopra. Si noti che il valore di ritorno della funzione
439408
`get_egg_label()` sarà importante. L'esempio di output del programma precedente
440409
sarebbe `71.23 large`.
441-
2. Un uovo sporco potrebbe avere una massa superiore a 90 grammi e un uovo rovinato o
442-
rotto probabilmente avrà una massa inferiore a 50 grammi. Modificare la funzione
443-
`get_egg_label()` per tenere conto di queste condizioni di errore. Un esempio di
444-
output potrebbe essere `25 too light, probably spoiled`.
410+
2. Un uovo sporco potrebbe avere una massa superiore a 90 grammi e un uovo rovinato o rotto probabilmente avrà una massa inferiore a 50 grammi. Modificare la funzione `get_egg_label()` per tenere conto di queste condizioni di errore. Un esempio di output potrebbe essere `25 too light, probably spoiled`.
445411

446412
::::::::::::::: solution
447413

448414
## Soluzione
449415

450416
```python
451417
def get_egg_label(mass):
452-
# egg sizing machinery prints a label
418+
# Il sistema di classificazione delle uova stampa un’etichetta.
453419
egg_label = "Unlabelled"
454420
if mass >= 90:
455421
egg_label = "warning: egg might be dirty"
@@ -503,10 +469,7 @@ japan = data_asia.loc['Japan']
503469
return avg
504470
```
505471

506-
3. Come generalizzereste questa funzione se non sapeste in anticipo quali anni specifici
507-
sono presenti come colonne nei dati? Per esempio, se avessimo anche i dati degli anni
508-
che terminano con 1 e 9 per ogni decennio? (Suggerimento: utilizzate le colonne per
509-
filtrare quelle che corrispondono al decennio, invece di enumerarle nel codice)
472+
3. Come generalizzereste questa funzione se non sapeste in anticipo quali anni specifici sono presenti come colonne nei dati? Per esempio, se avessimo anche i dati degli anni che terminano con 1 e 9 per ogni decennio? (Suggerimento: utilizzate le colonne per filtrare quelle che corrispondono al decennio, invece di enumerarle nel codice)
510473

511474
::::::::::::::: solution
512475

@@ -531,8 +494,7 @@ japan = data_asia.loc['Japan']
531494
return avg
532495
```
533496

534-
3. Per ottenere la media degli anni in questione, è necessario eseguire un ciclo su di
535-
essi:
497+
3. Per ottenere la media degli anni in questione, è necessario eseguire un ciclo su di essi:
536498

537499
```python
538500
def avg_gdp_in_decade(country, continent, year):
@@ -566,33 +528,17 @@ avg_gdp_in_decade('Japan','asia',1983)
566528

567529
## Simulazione di un sistema dinamico
568530

569-
In matematica, un [sistema dinamico](https://en.wikipedia.org/wiki/Dynamical_system) è
570-
un sistema in cui una funzione descrive la dipendenza temporale di un punto in uno
571-
spazio geometrico. Un esempio canonico di sistema dinamico è la [mappa
572-
logistica](https://en.wikipedia.org/wiki/Logistic_map), un modello di crescita che
573-
calcola una nuova densità di popolazione (tra 0 e 1) in base alla densità attuale. Nel
574-
modello, il tempo assume valori discreti 0, 1, 2, ...
531+
In matematica, un [sistema dinamico](https://en.wikipedia.org/wiki/Dynamical_system) è un sistema in cui una funzione descrive la dipendenza temporale di un punto in uno spazio geometrico. Un esempio canonico di sistema dinamico è la [mappa logistica](https://en.wikipedia.org/wiki/Logistic_map), un modello di crescita che calcola una nuova densità di popolazione (tra 0 e 1) in base alla densità attuale. Nel modello, il tempo assume valori discreti 0, 1, 2, ...
575532

576533
1. Definire una funzione chiamata `logistic_map` che prende due input: `x`, che
577-
rappresenta la popolazione attuale (al tempo `t`), e un parametro `r = 1`. Questa
578-
funzione deve restituire un valore che rappresenta lo stato del sistema (popolazione)
579-
al tempo `t + 1`, utilizzando la funzione di mappatura:
534+
rappresenta la popolazione attuale (al tempo `t`), e un parametro `r = 1`. Questa funzione deve restituire un valore che rappresenta lo stato del sistema (popolazione) al tempo `t + 1`, utilizzando la funzione di mappatura:
580535

581536
`f(t+1) = r * f(t) * [1 - f(t)]`
582537

583-
2. Utilizzando un ciclo `for` o `while`, iterare la funzione `logistic_map` definita
584-
nella parte 1, partendo da una popolazione iniziale di 0,5, per un periodo di tempo
585-
`t_final = 10`. Memorizzate i risultati intermedi in una lista, in modo da
586-
accumulare, al termine del ciclo, una sequenza di valori che rappresentano lo stato
587-
della mappa logistica al tempo `t = [0,1,...,t_final]` (11 valori in totale).
588-
Stampate questo elenco per vedere l'evoluzione della popolazione.
538+
2. Utilizzando un ciclo `for` o `while`, iterare la funzione `logistic_map` definita nella parte 1, partendo da una popolazione iniziale di 0,5, per un periodo di tempo `t_final = 10`. Memorizzate i risultati intermedi in una lista, in modo da accumulare, al termine del ciclo, una sequenza di valori che rappresentano lo stato della mappa logistica al tempo `t = [0,1,...,t_final]` (11 valori in totale).
539+
Stampate questo elenco per vedere l'evoluzione della popolazione.
589540

590-
3. Incapsulate la logica del vostro ciclo in una funzione chiamata `iterate` che prende
591-
la popolazione iniziale come primo input, il parametro `t_final` come secondo input e
592-
il parametro `r` come terzo input. La funzione deve restituire un elenco di valori
593-
che rappresentano lo stato della mappa logistica al tempo `t = [0,1,...,t_final]`.
594-
Eseguire la funzione per i periodi `t_final = 100` e `1000` e stampare alcuni dei
595-
valori. La popolazione sta tendendo verso uno stato stazionario?
541+
3. Incapsulate la logica del vostro ciclo in una funzione chiamata `iterate` che prende la popolazione iniziale come primo input, il parametro `t_final` come secondo input e il parametro `r` come terzo input. La funzione deve restituire un elenco di valori che rappresentano lo stato della mappa logistica al tempo `t = [0,1,...,t_final]`. Eseguire la funzione per i periodi `t_final = 100` e `1000` e stampare alcuni dei valori. La popolazione sta tendendo verso uno stato stazionario?
596542

597543
::::::::::::::: solution
598544

@@ -647,25 +593,24 @@ La popolazione sembra avvicinarsi allo zero.
647593
## Utilizzo di funzioni con condizionali in Pandas
648594

649595
Le funzioni contengono spesso dei condizionali. Ecco un breve esempio che indica in
650-
quale quartile si trova l'argomento in base ai valori codificati a mano per i punti di
651-
taglio del quartile.
596+
quale quartile si trova l'argomento in base ai valori codificati a mano per i punti di taglio del quartile.
652597

653598
```python
654599
def calculate_life_quartile(exp):
655600
if exp < 58.41:
656-
# This observation is in the first quartile
601+
# Questo si trova nel primo quartile
657602
return 1
658603
elif exp >= 58.41 and exp < 67.05:
659-
# This observation is in the second quartile
604+
# Questo si trova nel secondo quartile
660605
return 2
661606
elif exp >= 67.05 and exp < 71.70:
662-
# This observation is in the third quartile
607+
# Questo si trova nel terzo quartile
663608
return 3
664609
elif exp >= 71.70:
665-
# This observation is in the fourth quartile
610+
# Questo si trova nel quartp quartile
666611
return 4
667612
else:
668-
# This observation has bad data
613+
# Questo deriva da brutti dati
669614
return None
670615

671616
calculate_life_quartile(62.5)
@@ -675,29 +620,23 @@ calculate_life_quartile(62.5)
675620
2
676621
```
677622

678-
Questa funzione verrebbe tipicamente utilizzata all'interno di un ciclo `for`, ma Pandas
679-
ha un modo diverso e più efficiente per fare la stessa cosa, ovvero *applicare* una
680-
funzione a un dataframe o a una parte di esso. Ecco un esempio, utilizzando la
681-
definizione precedente.
623+
Questa funzione verrebbe tipicamente utilizzata all'interno di un ciclo `for`, ma Pandas ha un modo diverso e più efficiente per fare la stessa cosa, ovvero *applicare* una funzione a un dataframe o a una parte di esso. Ecco un esempio, utilizzando la definizione precedente.
682624

683625
```python
684626
data = pd.read_csv('data/gapminder_all.csv')
685627
data['life_qrtl'] = data['lifeExp_1952'].apply(calculate_life_quartile)
686628
```
687629

688-
C'è molto in questa seconda riga, quindi esaminiamola pezzo per pezzo. Sul lato destro
689-
di `=` iniziamo con `data['lifeExp']`, che è la colonna del dataframe chiamata `data`
690-
etichettata `lifExp`. Utilizziamo la `apply()` per fare ciò che dice, applicare la
691-
`calculate_life_quartile` al valore di questa colonna per ogni riga del dataframe.
630+
C'è molto in questa seconda riga, quindi esaminiamola pezzo per pezzo. Sul lato destro di `=` iniziamo con `data['lifeExp']`, che è la colonna del dataframe chiamata `data`etichettata `lifExp`. Utilizziamo la `apply()` per fare ciò che dice, applicare la `calculate_life_quartile` al valore di questa colonna per ogni riga del dataframe.
692631

693632

694633
::::::::::::::::::::::::::::::::::::::::::::::::::
695634

696635
:::::::::::::::::::::::::::::::::::::::: keypoints
697636

698-
- scomporre i programmi in funzioni per facilitarne la comprensione.
637+
- Scomporre i programmi in funzioni per facilitarne la comprensione.
699638
- Definire una funzione usando `def` con un nome, dei parametri e un blocco di codice.
700-
- Definire una funzione non la fa funzionare.
639+
- Definire una funzione non la esegue.
701640
- Gli argomenti di una chiamata di funzione sono abbinati ai suoi parametri definiti.
702641
- Le funzioni possono restituire un risultato al chiamante usando `return`.
703642

0 commit comments

Comments
 (0)