-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathil-vostro-primo-programma-python.html
395 lines (323 loc) · 40.2 KB
/
il-vostro-primo-programma-python.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
<!DOCTYPE html>
<meta charset=utf-8>
<title>Il vostro primo programma Python - Immersione in Python 3</title>
<!--[if IE]><script src=j/html5.js></script><![endif]-->
<link rel=stylesheet href=dip3.css>
<style>
body{counter-reset:h1 1}
table{border:1px solid #bbb;border-collapse:collapse;margin:auto}
td,th{border:1px solid #bbb;padding:0 1.75em}
th{text-align:left}
mark{display:inline}
</style>
<link rel=stylesheet media='only screen and (max-device-width: 480px)' href=mobile.css>
<link rel=stylesheet media=print href=print.css>
<meta name=viewport content='initial-scale=1.0'>
<form action=http://www.google.com/cse><div><input type=hidden name=cx value=014021643941856155761:l5eihuescdw><input type=hidden name=ie value=UTF-8> <input type=search name=q size=25 placeholder="powered by Google™"> <input type=submit name=sa value=Search></div></form>
<p>Voi siete qui: <a href=index.html>Inizio</a> <span class=u>‣</span> <a href=indice.html#il-vostro-primo-programma-python>Immersione in Python 3</a> <span class=u>‣</span>
<p id=level>Livello di difficoltà: <span class=u title=novizio>♦♢♢♢♢</span>
<h1>Il vostro primo programma Python</h1>
<blockquote class=q>
<p><span class=u>❝</span> Non nascondere le tue difficoltà dietro un silenzio da santo. Hai un problema? Ottimo. Rallegrati, immergiti e investiga. <span class=u>❞</span><br>— <a href=http://en.wikiquote.org/wiki/Buddhism>Ven. Henepola Gunaratana</a>
</blockquote>
<p id=toc>
<h2 id=divingin>Immersione!</h2>
<p class=f>Come accade per la maggior parte dei libri di programmazione, la convenzione imporrebbe di cominciare con una serie di capitoli noiosi sui fondamentali per poi arrivare gradualmente a costruire qualcosa di utile. Noi ci risparmieremo questa attesa. Qui di seguito troverete subito un programma Python completo e funzionante. Probabilmente ora non ha alcun senso per voi, ma non preoccupatevi perché lo analizzerete riga per riga. Provate comunque a leggerlo, prima di tutto, per vedere se riuscite a ricavarne qualcosa.
<p class=d>[<a href=esempi/humansize.py>scarica <code>humansize.py</code></a>]
<pre class=pp><code>SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
def approximate_size(size, a_kilobyte_is_1024_bytes=True):
'''Converte la dimensione di un file in una forma leggibile.
Argomenti con nome:
size -- dimensione del file in byte
a_kilobyte_is_1024_bytes -- se True (default), usa multipli di 1024
se False, usa multipli di 1000
Restituisce: stringa
'''
if size < 0:
raise ValueError('il numero non deve essere negativo')
multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
for suffix in SUFFIXES[multiple]:
size /= multiple
if size < multiple:
return '{0:.1f} {1}'.format(size, suffix)
raise ValueError('numero troppo grande')
if __name__ == '__main__':
print(approximate_size(1000000000000, False))
print(approximate_size(1000000000000))</code></pre>
<p>Ora eseguiamo il programma dalla riga di comando. Su Windows avremo qualcosa di simile a questo:
<pre class='nd screen'>
<samp class=p>c:\home\diveintopython3\esempi> </samp><kbd>c:\python31\python.exe humansize.py</kbd>
<samp>1.0 TB
931.3 GiB</samp></pre>
<p>Su Mac OS X o Linux avremo qualcosa di simile a questo:
<pre class='nd screen'>
<samp class=p>you@localhost:~/diveintopython3/esempi$ </samp><kbd>python3 humansize.py</kbd>
<samp>1.0 TB
931.3 GiB</samp></pre>
<p>Che cos’è appena successo? Avete eseguito il vostro primo programma Python. Avete invocato l’interprete Python dalla riga di comando e gli avete passato il nome dello script che volevate far eseguire all’interprete. Lo script definisce una singola funzione, la funzione <code>approximate_size()</code>, che prende una dimensione esatta di un file in byte e ne calcola una versione più “gradevole” (ma approssimata). Lo avete probabilmente visto fare in Esplora Risorse su Windows, o nel Finder di Mac OS X, oppure in Nautilus o Dolphin o Thunar su Linux. Se visualizzate una cartella di documenti come una lista a più colonne, il programma mostrerà una tabella con l’icona di ogni documento, il nome, la dimensione, il tipo, la data dell’ultima modifica, e così via. Se la cartella contiene un file di 1093 byte chiamato <code>TODO</code>, il vostro programma di gestione dei file non visualizzerà <code>TODO 1093 byte</code>, ma vi mostrerà qualcosa di simile a <code>TODO 1 KB</code>. Questo è ciò che fa la funzione <code>approximate_size()</code>.
<p>Guardate in fondo al programma e vedrete due chiamate a <code>print(approximate_size(<var>argomenti</var>))</code>. Queste sono invocazioni di funzione — prima chiamano la funzione <code>approximate_size()</code> passandole un certo numero di argomenti, poi prendono il valore di ritorno e lo passano direttamente alla funzione <code>print()</code>. La funzione <code>print()</code> è predefinita, perciò non ne vedrete mai la dichiarazione esplicita. Potete semplicemente usarla, sempre e ovunque. (Ci sono molte funzioni predefinite e molte altre funzioni che sono suddivise in <i>moduli</i>. Sii paziente, cavalletta.)
<p>Quindi, perché l’esecuzione dello script dalla riga di comando vi restituisce ogni volta gli stessi risultati? Ci arriveremo. Prima di tutto, diamo un’occhiata alla funzione <code>approximate_size()</code>.
<p class=a>⁂
<h2 id=declaringfunctions>Dichiarare funzioni</h2>
<p>Python vi permette di scrivere funzioni come la maggior parte degli altri linguaggi, ma non utilizza file di intestazione separati come il <abbr>C++</abbr> o sezioni di <code>interface</code>/<code>implementation</code> come il Pascal. Quando avete bisogno di una funzione, vi basta dichiararla, in questo modo:
<pre class='nd pp'><code>def approximate_size(size, a_kilobyte_is_1024_bytes=True):</code></pre>
<aside>Quando avete bisogno di una funzione, vi basta dichiararla.</aside>
<p>La parola chiave <code>def</code> inizia la dichiarazione di funzione, seguita dal nome della funzione, seguito dagli argomenti della funzione racchiusi tra parentesi. Gli argomenti sono separati da virgole.
<p>Notate anche che la funzione non definisce un tipo di dato di ritorno. Le funzioni Python non specificano il tipo di dato del loro valore di ritorno, non specificano nemmeno se restituiscono o no un valore. (In effetti, ogni funzione Python restituisce un valore: se la funzione esegue un’istruzione <code>return</code>, restituirà quel valore, altrimenti restituirà <code>None</code>, il valore nullo di Python.)
<blockquote class=note>
<p><span class=u>☞</span>In alcuni linguaggi, le funzioni (che restituiscono un valore) cominciano con <code>function</code> e le procedure (che non restituiscono un valore) cominciano con <code>sub</code>. Non ci sono procedure in Python. Ci sono solo funzioni, tutte le funzioni restituiscono un valore (anche se è <code>None</code>) e tutte le funzioni cominciano con <code>def</code>.
</blockquote>
<p>La funzione <code>approximate_size()</code> accetta due argomenti — <var>size</var> e <var>a_kilobyte_is_1024_bytes</var> — ma nessun argomento dichiara il proprio tipo. In Python, le variabili non sono mai esplicitamente tipate. L’interprete Python capisce da solo qual è il tipo di una variable e ne tiene traccia internamente.
<blockquote class='note compare java'>
<p><span class=u>☞</span>In Java e in altri linguaggi staticamente tipati, dovete dichiarare il tipo del valore di ritorno e di ogni argomento della funzione. In Python, i tipi non vengono mai dichiarati. Sulla base del valore che viene assegnato, Python tiene traccia del tipo di dato internamente.
</blockquote>
<h3 id=optional-arguments>Argomenti opzionali e con nome</h3>
<p>Python consente agli argomenti di funzione di avere valori predefiniti, in modo che, se una funzione viene chiamata senza un argomento, quell’argomento venga impostato al suo valore predefinito. In più, gli argomenti possono essere specificati in qualsiasi ordine usando argomenti con nome.
<p>Diamo un’altra occhiata a quella dichiarazione della funzione <code>approximate_size()</code>:
<pre class='nd pp'><code>def approximate_size(size, a_kilobyte_is_1024_bytes=True):</code></pre>
<p>Il secondo argomento, <var>a_kilobyte_is_1024_bytes</var>, specifica un valore predefinito pari a <code>True</code>. Questo significa che l’argomento è <i>opzionale</i>: potete invocare la funzione senza di esso e Python opererà come se l’aveste invocata passando <code>True</code> come secondo parametro.
<p>Ora guardate in fondo allo script:
<pre class=pp><code>if __name__ == '__main__':
<a> print(approximate_size(1000000000000, False)) <span class=u>①</span></a>
<a> print(approximate_size(1000000000000)) <span class=u>②</span></a></code></pre>
<ol>
<li>Questa riga invoca la funzione <code>approximate_size()</code> con due argomenti. All’interno della funzione <code>approximate_size()</code>, <var>a_kilobyte_is_1024_bytes</var> varrà <code>False</code>, dato che avete esplicitamente passato <code>False</code> come secondo argomento.
<li>Questa riga invoca la funzione <code>approximate_size()</code> con un solo argomento. Ma questo va ancora bene, perché il secondo argomento è opzionale! Dato che il chiamante non lo specifica, il secondo argomento assumerà il proprio valore predefinito <code>True</code>, come stabilito nella dichiarazione di funzione.
</ol>
<p>I valori degli argomenti di una funzione possono anche essere passati per nome.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>from humansize import approximate_size</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>approximate_size(4000, a_kilobyte_is_1024_bytes=False)</kbd> <span class=u>①</span></a>
<samp class=pp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>approximate_size(size=4000, a_kilobyte_is_1024_bytes=False)</kbd> <span class=u>②</span></a>
<samp class=pp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>approximate_size(a_kilobyte_is_1024_bytes=False, size=4000)</kbd> <span class=u>③</span></a>
<samp class=pp>'4.0 KB'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>approximate_size(a_kilobyte_is_1024_bytes=False, 4000)</kbd> <span class=u>④</span></a>
<samp class=traceback> File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg</samp>
<a><samp class=p>>>> </samp><kbd class=pp>approximate_size(size=4000, False)</kbd> <span class=u>⑤</span></a>
<samp class=traceback> File "<stdin>", line 1
SyntaxError: non-keyword arg after keyword arg</samp></pre>
<ol>
<li>Questa è un’invocazione della funzione <code>approximate_size()</code> con <code>4000</code> come valore per il primo argomento (<var>size</var>) e <code>False</code> come valore per il secondo argomento chiamato <var>a_kilobyte_is_1024_bytes</var>. (Si dà il caso che questo sia effettivamente il secondo argomento, ma la cosa non ha importanza, come vedrete fra un minuto.)
<li>Questa è un’invocazione della funzione <code>approximate_size()</code> con <code>4000</code> come valore per l’argomento chiamato <var>size</var> e <code>False</code> come valore per l’argomento chiamato <var>a_kilobyte_is_1024_bytes</var>. (Si dà il caso che questi argomenti con nome siano nello stesso ordine in cui sono elencati gli argomenti nella dichiarazione di funzione, ma anche questo non ha importanza.)
<li>Questa è un’invocazione della funzione <code>approximate_size()</code> con <code>False</code> come valore per l’argomento chiamato <var>a_kilobyte_is_1024_bytes</var> e <code>4000</code> come valore per l’argomento chiamato <var>size</var>. (Vedete? Vi avevo detto che l’ordine non ha importanza.)
<li>Questa invocazione fallisce, perché passate un argomento con nome seguito da un argomento (di tipo posizionale) senza nome, e questo non funziona mai. Leggendo la lista degli argomenti da sinistra a destra, una volta che utilizzate un singolo argomento con nome anche il resto degli argomenti deve essere dello stesso tipo.
<li>Anche questa invocazione fallisce, per lo stesso motivo della precedente. Vi sorprende? Dopo tutto, avete passato <code>4000</code> come valore per l’argomento chiamato <code>size</code>, poi “ovviamente” intendevate passare quel valore <code>False</code> all’argomento <var>a_kilobyte_is_1024_bytes</var>. Ma Python non funziona in questo modo. Appena utilizzate un argomento con nome, anche tutti gli argomenti alla destra di quell’argomento devono essere argomenti con nome.
</ol>
<p class=a>⁂
<h2 id=readability>Scrivere codice leggibile</h2>
<p>Non vi annoierò con una lunga predica sull’importanza di documentare il vostro codice. Vi basti sapere che il codice viene scritto una volta sola ma letto molte volte, e che i lettori più importanti del vostro codice siete voi stessi, sei mesi dopo averlo scritto (cioè dopo che vi siete dimenticati tutto ma avete bisogno di correggere qualcosa). Python facilita la scrittura di codice leggibile, perciò avvantaggiatevene. Fra sei mesi mi ringrazierete.
<h3 id=docstrings>Stringhe di documentazione</h3>
<p>Potete documentare una funzione Python aggiungendole una stringa di documentazione (chiamata <code>docstring</code> per brevità). Nel nostro programma, la funzione <code>approximate_size()</code> è stata dotata di una <code>docstring</code>:
<pre class='nd pp'><code>def approximate_size(size, a_kilobyte_is_1024_bytes=True):
'''Converte la dimensione di un file in una forma leggibile.
Argomenti con nome:
size -- dimensione del file in byte
a_kilobyte_is_1024_bytes -- se True (default), usa multipli di 1024
se False, usa multipli di 1000
Restituisce: stringa
'''</code></pre>
<aside>Ogni funzione merita una docstring decente.</aside>
<p>Le triple virgolette servono per rappresentare una stringa su più righe. Ogni cosa tra le virgolette di inizio e di fine è parte di una singola stringa, inclusi i ritorni a capo, gli spazi bianchi all’inizio di una riga e altri caratteri di virgolette. Le triple virgolette si possono usare dovunque, ma le vedrete sfruttate soprattutto nella definizione di una <code>docstring</code>.
<blockquote class='note compare perl5'>
<p><span class=u>☞</span>Le triple virgolette sono anche un modo facile per definire una stringa che contiene sia apici che virgolette, come <code>qq/.../</code> in Perl 5.
</blockquote>
<p>Tutto quello che si trova tra le triple virgolette rappresenta la <code>docstring</code> della funzione, che documenta ciò che la funzione fa. Una <code>docstring</code>, se esiste, deve essere la prima cosa definita in una funzione (cioè, nella riga subito dopo la dichiarazione di funzione). Non avete tecnicamente bisogno di dotare la vostra funzione di una <code>docstring</code>, ma dovreste sempre farlo. So che lo avete sentito in ogni corso di programmazione che avete seguito, ma Python vi dà un incentivo aggiuntivo: la <code>docstring</code> è disponibile a tempo di esecuzione sotto forma di attributo della funzione.
<blockquote class=note>
<p><span class=u>☞</span>Molti <abbr>IDE</abbr> per Python usano le <code>docstring</code> per fornire documentazione sensibile al contesto, in modo che quando scrivete il nome di una funzione la sua <code>docstring</code> appaia sotto forma di suggerimento. Questa caratteristica può essere incredibilmente utile, ma lo è solamente tanto quanto le <code>docstring</code> che scrivete.
</blockquote>
<p class=a>⁂
<h2 id=importsearchpath>Il percorso di ricerca di <code>import</code></h2>
<p>Prima di proseguire, voglio menzionare brevemente il percorso di ricerca delle librerie. Python guarda in diversi posti quando provate a importare un modulo. Nello specifico, guarda in tutte le directory definite in <code>sys.path</code>. Questo attributo è semplicemente una lista e potete facilmente vederlo o modificarlo con i metodi standard delle liste. (Imparerete di più sulle liste nel capitolo sui <a href=tipi-di-dato-nativi.html>tipi di dato nativi</a>.)
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>import sys</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>sys.path</kbd> <span class=u>②</span></a>
<samp class=pp>['',
'/usr/lib/python31.zip',
'/usr/lib/python3.1',
'/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@',
'/usr/lib/python3.1/lib-dynload',
'/usr/lib/python3.1/dist-packages',
'/usr/local/lib/python3.1/dist-packages']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>sys</kbd> <span class=u>③</span></a>
<samp><module 'sys' (built-in)></samp>
<a><samp class=p>>>> </samp><kbd class=pp>sys.path.insert(0, '/home/mark/diveintopython3/esempi')</kbd> <span class=u>④</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>sys.path</kbd> <span class=u>⑤</span></a>
<samp class=pp>['/home/mark/diveintopython3/esempi',
'',
'/usr/lib/python31.zip',
'/usr/lib/python3.1',
'/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@',
'/usr/lib/python3.1/lib-dynload',
'/usr/lib/python3.1/dist-packages',
'/usr/local/lib/python3.1/dist-packages']</samp></pre>
<ol>
<li>Importare il modulo <code>sys</code> rende disponibili tutte le sue funzioni e i suoi attributi.
<li><code>sys.path</code> è una lista di nomi di directory che costituiscono il percorso di ricerca corrente. (Il vostro apparirà diverso, a seconda del vostro sistema operativo, della versione di Python che state eseguendo e di dove è stata originariamente installata.) Python cercherà attraverso queste directory (in questo ordine) un file con estensione <code>.py</code> il cui nome corrisponda a quello che state tentando di importare.
<li>In realtà, ho mentito; la verità è più complicata di così, perché non tutti i moduli sono memorizzati come file <code>.py</code>. Alcuni sono moduli <i>built-in</i>, integrati direttamente all’interno dell’interprete Python. I moduli built-in si comportano esattamente come gli altri moduli, ma il loro codice sorgente Python non è disponibile, perché non sono scritti in Python! (Come lo stesso interprete del linguaggio, questi moduli sono scritti in C.)
<li>Potete aggiungere a tempo di esecuzione una nuova directory al percorso di ricerca di Python aggiungendo il nome della directory a <code>sys.path</code>; successivamente, Python guarderà anche in quella directory ogni volta che provate a importare un modulo. L’effetto dura fino a quando l’interprete Python è in esecuzione.
<li>Usando <code>sys.path.insert(0, <var>nuovo_percorso</var>)</code>, avete inserito una nuova directory come primo elemento della lista <code>sys.path</code>, quindi all’inizio del percorso di ricerca di Python. Questo è quasi sempre quello che desiderate. In caso di un conflitto di nomi (per esempio, nel caso l’interprete Python includa la versione 2 di una particolare libreria ma voi vogliate usarne la versione 3), questo vi assicura che saranno i vostri moduli a essere trovati e utilizzati invece dei moduli distribuiti insieme all’interprete Python.
</ol>
<p class=a>⁂
<h2 id=everythingisanobject>Ogni cosa è un oggetto</h2>
<p>Nel caso vi fosse sfuggito, ho appena detto che le funzioni Python sono dotate di attributi e che questi attributi sono disponibili a tempo di esecuzione. Una funzione, come ogni altra cosa in Python, è un oggetto.
<p>Lanciate la shell interattiva di Python e seguitemi attraverso questa serie di istruzioni:
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>import humansize</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>print(humansize.approximate_size(4096, True))</kbd> <span class=u>②</span></a>
<samp class=pp>4.0 KiB</samp>
<a><samp class=p>>>> </samp><kbd class=pp>print(humansize.approximate_size.__doc__)</kbd> <span class=u>③</span></a>
<samp>Converte la dimensione di un file in una forma leggibile.
Argomenti con nome:
size -- dimensione del file in byte
a_kilobyte_is_1024_bytes -- se True (default), usa multipli di 1024
se False, usa multipli di 1000
Restituisce: stringa
</samp></pre>
<ol>
<li>La prima riga importa il programma <code>humansize</code> come un modulo — un pezzo di codice che potete usare interattivamente o da un programma Python più grande. Una volta importato un modulo, potete fare riferimento a ogni funzione, classe, o attributo pubblico che appartiene al modulo. I moduli possono sfruttare questa loro caratteristica per accedere alle funzionalità di altri moduli, e voi potete farlo anche nella shell interattiva di Python. Questo è un concetto importante, e lo vedrete ribadito più volte nel seguito di questo libro.
<li>Quando volete usare funzioni definite in moduli importati, dovete includere il nome del modulo. Quindi non potete semplicemente dire <code>approximate_size</code>, ma dovete scrivere <code>humansize.approximate_size</code>. Se avete usato le classi in Java, la sintassi dovrebbe risultarvi vagamente familiare.
<li>Invece di invocare la funzione, avete richiesto uno dei suoi attributi, <code>__doc__</code>.
</ol>
<blockquote class='note compare perl5'>
<p><span class=u>☞</span><code>import</code> in Python è come <code>require</code> in Perl. Una volta che avete importato un modulo Python tramite <code>import</code>, potete accedere alle sue funzioni con la sintassi <code><var>modulo</var>.<var>funzione</var></code>; una volta che avete richiesto un modulo Perl tramite <code>require</code>, potete accedere alle sue funzioni con la sintassi <code><var>modulo</var>::<var>funzione</var></code>.
</blockquote>
<h3 id=whatsanobject>Che cos’è un oggetto?</h3>
<p>Ogni cosa in Python è un oggetto, e ogni cosa può possedere attributi e metodi. Tutte le funzioni hanno un attributo built-in <code>__doc__</code>, che restituisce la <var>docstring</var> definita nel codice sorgente della funzione. Il modulo <code>sys</code> è un oggetto che ha (tra le altre cose) un attributo chiamato <var>path</var>. E così via.
<p>Tuttavia, questo non risponde alla domanda fondamentale: che cos’è un oggetto? Linguaggi di programmazione differenti definiscono “oggetto” in modi differenti. In alcuni, significa che <em>tutti</em> gli oggetti <em>devono</em> avere attributi e metodi; in altri, significa che tutti gli oggetti sono estendibili. In Python, la definizione è più lasca. Alcuni oggetti non hanno attributi né metodi, <em>ma potrebbero averli</em>. Non tutti gli oggetti sono estendibili. Ma ogni cosa è un oggetto nel senso che può essere assegnata a una variabile o passata come argomento a una funzione.
<p>Potreste aver udito il termine “oggetto di prima classe” in altri contesti legati alla programmazione. In Python, le funzioni sono <i>oggetti di prima classe</i>. Potete passare una funzione come argomento a un’altra funzione. I moduli sono <i>oggetti di prima classe</i>. Potete passare un intero modulo come argomento a una funzione. Le classi sono oggetti di prima classe e anche le singole istanze di una classe sono oggetti di prima classe.
<p>Questo concetto è importante, quindi lo ripeterò nel caso vi fosse sfuggito le prime volte: <em>ogni cosa in Python è un oggetto</em>. Le strighe sono oggetti. Le liste sono oggetti. Le funzioni sono oggetti. Le classi sono oggetti. Le istanze di una classe sono oggetti. Persino i moduli sono oggetti.
<p class=a>⁂
<h2 id=indentingcode>Indentare il codice</h2>
<p>Le funzioni Python non cominciano esplicitamente con <code>begin</code> né terminano con <code>end</code>, e non ci sono parentesi graffe a indicare dove il codice della funzione inizia e finisce. I due punti (<code>:</code>) e l’indentazione del codice sono gli unici delimitatori.
<pre class=pp><code><a>def approximate_size(size, a_kilobyte_is_1024_bytes=True): <span class=u>①</span></a>
<a> if size < 0: <span class=u>②</span></a>
<a> raise ValueError('il numero non deve essere negativo') <span class=u>③</span></a>
<a> <span class=u>④</span></a>
multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
<a> for suffix in SUFFIXES[multiple]: <span class=u>⑤</span></a>
size /= multiple
if size < multiple:
return '{0:.1f} {1}'.format(size, suffix)
raise ValueError('numero troppo grande')</code></pre>
<ol>
<li>I blocchi di codice sono definiti dalla loro indentazione. Per “blocco di codice” intendo funzioni, istruzioni <code>if</code>, cicli <code>for</code>, cicli <code>while</code>, e così via. La presenza di un’indentazione comincia un blocco e la sua assenza lo termina. Non ci sono parentesi graffe, parentesi quadre, o parole chiave. Questo vuol dire che gli spazi bianchi sono significativi e devono essere consistenti. In questo esempio, il codice della funzione è indentato di quattro spazi. Non è necessario che siano quattro spazi, c’è solo bisogno che l’indentazione sia consistente. La prima riga che non è indentata indica la fine della funzione.
<li>In Python, un’istruzione <code>if</code> è seguita da un blocco di codice. Se l’espressione di <code>if</code> viene valutata come vera, il blocco indentato viene eseguito, altrimenti si ricade nel blocco di <code>else</code> (se esiste). Notate la mancanza di parentesi attorno all’espressione.
<li>Questa riga è dentro il blocco di codice dell’<code>if</code>. L’istruzione di <code>raise</code> solleverà un’eccezione (di tipo <code>ValueError</code>), ma solo se <code>size < 0</code>.
<li>Questa <em>non</em> è la fine della funzione. Le righe completamente vuote non vengono considerate. Possono rendere il codice più leggibile, ma non vengono usate per delimitare i blocchi. La funzione continua nella riga seguente.
<li>Anche il ciclo <code>for</code> segnala l’inizio di un blocco di codice. I blocchi di codice possono contenere più righe, fino a quando esse sono indentate della stessa quantità. Questo ciclo <code>for</code> contiene tre righe di codice. Non c’è nessun’altra sintassi speciale per blocchi di codice su più righe. Indentate e andate avanti con la vostra vita.
</ol>
<p>Dopo alcune proteste iniziali e diverse analogie maliziose al Fortran, vi riappacificherete con questa caratteristica di Python e comincerete a vederne i lati positivi. Uno dei maggiori benefici è che tutti i programmi Python appaiono simili, in quanto l’indentazione è un requisito del linguaggio e non una questione di stile. Questo rende più facile leggere e comprendere il codice Python scritto da altre persone.
<blockquote class='note compare java'>
<p><span class=u>☞</span>Python usa i ritorni a capo per separare le istruzioni e i due punti e l’indentazione per separare i blocchi di codice. <abbr>C++</abbr> e Java usano i punti e virgola per separare le istruzioni e le parentesi graffe per separare i blocchi di codice.
</blockquote>
<p class=a>⁂
<h2 id=exceptions>Eccezioni</h2>
<p>Le eccezioni sono dappertutto in Python. Virtualmente ogni modulo nella libreria standard le usa e lo stesso interprete Python le solleverà in molte circostanze differenti. Le vedrete ripetutamente nel corso di questo libro.
<p>Che cos’è un’eccezione? Di solito è un errore, un’indicazione che qualcosa è andata storta. (Non tutte le eccezioni sono errori, ma non preoccupatevi di questo per ora.) Alcuni linguaggi di programmazione incoraggiano l’uso di codici di errore di ritorno, che vengono <em>controllati</em>. Python incoraggia l’uso delle eccezioni, che vengono <em>gestite</em>.
<p>Quando avviene un errore nella Shell Python, vengono stampati alcuni dettagli sull’eccezione e su come è avvenuta, e questo è tutto. Questa viene chiamata un’eccezione <em>non gestita</em>. Quando l’eccezione è stata sollevata, non c’era alcuna istruzione per notarla esplicitamente e affrontarla, quindi è gorgogliata in superficie fino al livello della Shell Python, che sputa fuori alcune informazioni di debug e considera finito il proprio lavoro. Nella shell questo non è un grande problema, ma se accadesse mentre il vostro programma Python è in esecuzione, l’intero programma si bloccherebbe nel caso l’eccezione non venisse gestita. Magari questo è il comportamento che desiderate, magari non lo è.
<blockquote class='note compare java'>
<p><span class=u>☞</span>A differenza di Java, le funzioni Python non dichiarano quali eccezioni potrebbero sollevare. Sta a voi determinare quali possibili eccezioni avete bisogno di catturare.
</blockquote>
<p>Un’eccezione non deve necessariamente risultare in un completo blocco del programma, comunque. Le eccezioni possono essere <em>gestite</em>. A volte un’eccezione compare perché in realtà il vostro codice ha un bug (come il tentativo di accedere a una variabile che non esiste), ma altre volte un’eccezione è qualcosa che potete anticipare. Se state aprendo un file, quel file potrebbe non esistere. Se state importando un modulo, quel modulo potrebbe non essere installato. Se state aprendo una connessione a un database, quel database potrebbe non essere disponibile, oppure potreste non avere le credenziali di sicurezza corrette per accedere. Se sapete che una riga di codice potrebbe sollevare un’eccezione, dovreste gestire l’eccezione usando un blocco <code>try...except</code>.
<blockquote class='note compare java'>
<p><span class=u>☞</span>Python usa blocchi <code>try...except</code> per gestire le eccezioni e l’istruzione <code>raise</code> per generarle. Java e <abbr>C++</abbr> usano blocchi <code>try...catch</code> per gestire le eccezioni e l’istruzione <code>throw</code> per generarle.
</blockquote>
<p>La funzione <code>approximate_size()</code> solleva eccezioni in due casi differenti: se la variabile <var>size</var> passata contiene una dimensione più grande di quella che la funzione è progettata per gestire, o se contiene una dimensione inferiore a zero.
<pre class='nd pp'><code>if size < 0:
raise ValueError('il numero non deve essere negativo')</code></pre>
<p>La sintassi per sollevare un’eccezione è abbastanza semplice. Usate l’istruzione <code>raise</code>, seguita dal nome dell’eccezione e da una stringa contenente un messaggio per scopi di debug. La sintassi ricorda quella dell’invocazione di una funzione. (In realtà, le eccezioni sono implementate come classi e questa istruzione <code>raise</code> crea effettivamente un’istanza della classe <code>ValueError</code> passando la stringa <code>'il numero non deve essere negativo'</code> al suo metodo di inizializzazione. Ma <a href=iteratori.html#defining-classes>stiamo mettendo il carro avanti ai buoi</a>!)
<blockquote class=note>
<p><span class=u>☞</span>Non avete bisogno di gestire un’eccezione nella funzione che la solleva. Se una funzione non gestisce un’eccezione, l’eccezione viene passata alla funzione chiamante, poi alla funzione che ha chiamato quella funzione, e così via “fino alla cima dello stack di esecuzione”. Se l’eccezione non viene mai gestita, il vostro programma si bloccherà, Python stamperà una “traccia dello stack” sul canale di errore e le cose finiranno lì. Ancora una volta, forse questo è il comportamento che desiderate; dipende da ciò che fa il vostro programma.
</blockquote>
<h3 id=importerror>Catturare gli errori di importazione</h3>
<p>Una delle eccezioni predefinite di Python è <code>ImportError</code>, che viene sollevata quando cercate di importare un modulo e l’operazione fallisce. Questo può succedere per una varietà di ragioni, ma il caso più semplice è quello in cui il modulo non esiste nel vostro <a href=#importsearchpath>percorso di ricerca per le importazioni</a>. Potete usare questa eccezione per includere funzionalità opzionali nel vostro programma. Per esempio, <a href=caso-di-studio-convertire-chardet-verso-python-3.html>la libreria <code>chardet</code></a> fornisce il riconoscimento automatico delle codifiche di carattere. Forse il vostro programma desidera usare questa libreria <em>se esiste</em>, ma continuare normalmente se l’utente non l’ha installata. Potete fare questo con un blocco <code>try..except</code>.
<pre class='nd pp'><code><mark>try</mark>:
import chardet
<mark>except</mark> ImportError:
chardet = None</code></pre>
<p>Più tardi, potete controllare la presenza del modulo <code>chardet</code> con una semplice istruzione <code>if</code>:
<pre class='nd pp'><code>if chardet:
# fai qualcosa
else:
# continua comunque</code></pre>
<p>L’eccezione <code>ImportError</code> viene comunemente usata anche quando due moduli implementano una <abbr>API</abbr> comune, ma uno è più desiderabile dell’altro perché magari è più veloce o usa meno memoria. Potete provare a importare un modulo ma ripiegare su un modulo differente se la prima importazione fallisce. Per esempio, <a href=xml.html>il capitolo su XML</a> parla di due moduli che implementano una <abbr>API</abbr> comune chiamata <code>ElementTree</code>. Il primo, <code>lxml</code>, è un modulo di terze parti che dovete scaricare e installare da voi. Il secondo, <code>xml.etree.ElementTree</code>, è più lento ma è parte della libreria standard di Python 3.
<pre class='nd pp'><code>try:
from lxml import etree
except ImportError:
import xml.etree.ElementTree as etree</code></pre>
<p>Alla fine di questo blocco <code>try..except</code> avrete importato un <em>qualche</em> modulo e l’avrete chiamato <var>etree</var>. Dato che entrambi i moduli implementano una <abbr>API</abbr> comune, il resto del vostro programma non deve controllare ogni volta quale modulo è stato importato. E dato che il modulo che <em>è</em> stato importato viene sempre chiamato <var>etree</var>, non c’è bisogno di spargere istruzioni <code>if</code> ovunque nel resto del vostro programma per chiamare moduli con nomi differenti.
<p class=a>⁂
<h2 id=nameerror>Variabili non legate</h2>
<p>Date un’altra occhiata a questa riga di codice nella funzione <code>approximate_size()</code>:
<pre class='nd pp'><code>multiple = 1024 if a_kilobyte_is_1024_bytes else 1000</code></pre>
<p>Non dichiarate mai la variabile <var>multiple</var>, ma le assegnate semplicemente un valore. Questo va bene, perché Python vi permette di farlo. Quello che Python <em>non</em> vi permette è fare riferimento a una variabile a cui non è mai stato assegnato un valore. Il tentativo di fare questo solleverà un’eccezione di tipo <code>NameError</code>.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>x</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined</samp>
<samp class=p>>>> </samp><kbd class=pp>x = 1</kbd>
<samp class=p>>>> </samp><kbd class=pp>x</kbd>
<samp class=pp>1</samp></pre>
<p>Un giorno ringrazierete Python per questo.
<p class=a>⁂
<h2 id=case>Ogni cosa è sensibile alle maiuscole</h2>
<p>Tutti i nomi in Python sono sensibili alle maiuscole: nomi di variabile, nomi di funzione, nomi di classe, nomi di modulo, nomi di eccezione. Se potete ottenerlo, impostarlo, invocarlo, costruirlo, importarlo, o sollevarlo, allora è sensibile alle maiuscole.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>an_integer = 1</kbd>
<samp class=p>>>> </samp><kbd class=pp>an_integer</kbd>
<samp class=pp>1</samp>
<samp class=p>>>> </samp><kbd>AN_INTEGER</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'AN_INTEGER' is not defined</samp>
<samp class=p>>>> </samp><kbd>An_Integer</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'An_Integer' is not defined</samp>
<samp class=p>>>> </samp><kbd>an_inteGer</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'an_inteGer' is not defined</samp>
</pre>
<p>E così via.
<p class=a>⁂
<h2 id=runningscripts>Eseguire gli script</h2>
<aside>Ogni cosa in Python è un oggetto.</aside>
<p>I moduli Python sono oggetti e hanno diversi attributi utili. Potete sfruttare questa caratteristica per collaudare facilmente i vostri moduli mentre li scrivete, includendo uno speciale blocco di codice che viene eseguito quando lanciate il file Python dalla riga di comando. Considerate le ultime righe di <code>humansize.py</code>:
<pre class='nd pp'><code>
if __name__ == '__main__':
print(approximate_size(1000000000000, False))
print(approximate_size(1000000000000))</code></pre>
<blockquote class='note compare clang'>
<p><span class=u>☞</span>Come il <abbr>C</abbr>, Python usa <code>==</code> per il confronto e <code>=</code> per l’assegnamento. A differenza del <abbr>C</abbr>, Python non supporta l’assegnamento in linea, quindi non c’è alcuna possibilità di assegnare accidentalmente il valore che pensavate di stare confrontando.
</blockquote>
<p>Che cosa rende speciale questa istruzione <code>if</code>? Ebbene, i moduli sono oggetti, e tutti i moduli hanno l’attributo built-in <code>__name__</code>. Il valore dell’attributo <code>__name__</code> di un modulo dipende da come state usando il modulo. Se importate un modulo, allora <code>__name__</code> sarà il nome del file del modulo, senza il percorso e l’estensione.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>import humansize</kbd>
<samp class=p>>>> </samp><kbd class=pp>humansize.__name__</kbd>
<samp class=pp>'humansize'</samp></pre>
<p>Ma potete anche eseguire direttamente il modulo come un programma a sé, nel qual caso <code>__name__</code> sarà lo speciale valore predefinito <code>__main__</code>. Nel nostro esempio, Python valuterà l’istruzione <code>if</code>, troverà un’espressione vera ed eseguirà il blocco di codice corrispondente. In questo caso, per stampare due valori.
<pre class='nd screen'>
<samp class=p>c:\home\diveintopython3> </samp><kbd>c:\python31\python.exe humansize.py</kbd>
<samp>1.0 TB
931.3 GiB</samp></pre>
<p>E questo è il vostro primo programma Python!
<p class=a>⁂
<h2 id=furtherreading>Letture di approfondimento</h2>
<ul>
<li><a href=http://www.python.org/dev/peps/pep-0257/><abbr>PEP</abbr> 257: Convenzioni per le docstring</a> spiega cosa distingue una buona <code>docstring</code> da una <code>docstring</code> eccellente.
<li><a href=http://docs.python.org/3.1/tutorial/controlflow.html#documentation-strings>Tutorial Python: stringhe di documentazione</a> si occupa a sua volta dell’argomento.
<li><a href=http://www.python.org/dev/peps/pep-0008/><abbr>PEP</abbr> 8: Guida allo stile per il codice Python</a> descrive il buon stile di indentazione.
<li><a href=http://docs.python.org/3.1/reference/><cite>Guida di riferimento a Python</cite></a> spiega cosa significa dire che <a href=http://docs.python.org/3.1/reference/datamodel.html#objects-values-and-types>ogni cosa in Python è un oggetto</a>, perché alcune persone sono <a href=http://www.douglasadams.com/dna/pedants.html>pedanti</a> e adorano discutere questo tipo di cose in lungo e in largo.
</ul>
<p class=v><a href=installare-python.html rel=prev title='indietro a “Installare Python”'><span class=u>☜</span></a> <a rel=next href=tipi-di-dato-nativi.html title='avanti a “Tipi di dato nativi”'><span class=u>☞</span></a>
<p class=c>© 2001–10 <a href=informazioni-sul-libro.html>Mark Pilgrim</a><br>
© 2009–10 <a href=informazioni-sulla-traduzione.html>Giulio Piancastelli</a> per la traduzione italiana
<script src=j/jquery.js></script>
<script src=j/prettify.js></script>
<script src=j/dip3.js></script>