-
Notifications
You must be signed in to change notification settings - Fork 0
/
tipi-di-dato-nativi.html
965 lines (891 loc) · 79 KB
/
tipi-di-dato-nativi.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
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
<!DOCTYPE html>
<meta charset=utf-8>
<title>Tipi di dato nativi - 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 2}
</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=root value=Search></div></form>
<p>Voi siete qui: <a href=index.html>Inizio</a> <span class=u>‣</span> <a href=indice.html#tipi-di-dato-nativi>Immersione in Python 3</a> <span class=u>‣</span>
<p id=level>Livello di difficoltà: <span class=u title=principiante>♦♦♢♢♢</span>
<h1>Tipi di dato nativi</h1>
<blockquote class=q>
<p><span class=u>❝</span> Lo stupore è la base di ogni filosofia, la ricerca ne è il procedimento, l’ignoranza la fine. <span class=u>❞</span><br>— Michel de Montaigne
</blockquote>
<p id=toc>
<h2 id=divingin>Immersione!</h2>
<p class=f>Disinteressatevi del <a href=il-vostro-primo-programma-python.html>vostro primo programma Python</a> per un minuto, e parliamo di tipi di dato. In Python, <a href=il-vostro-primo-programma-python.html#declaringfunctions>ogni valore ha un tipo di dato</a>, ma non è necessario dichiarare il tipo di dato delle variabili. Come mai? In base all’assegnamento originale di ogni variabile, Python capisce di quale tipo è e ne tiene traccia internamente.
<p>Python ha molti tipi di dato nativi. Questi sono quelli più importanti:
<ol>
<li><b>Booleani</b>: sono solamente <code>True</code> oppure <code>False</code>.
<li><b>Numeri</b>: possono essere interi (<code>1</code> e <code>2</code>), reali (<code>1.1</code> e <code>1.2</code>), frazioni (<code>1/2</code> e <code>2/3</code>), o persino <a href=http://it.wikipedia.org/wiki/Numero_complesso>numeri complessi</a>.
<li><b>Stringhe</b>: sono sequenze di caratteri Unicode, per esempio un documento <abbr>HTML</abbr>.
<li><b>Byte</b> e <b>byte array</b>: per esempio un file <abbr>JPEG</abbr> contenente un’immagine.
<li><b>Liste</b>: sono sequenze ordinate di valori.
<li><b>Tuple</b>: sono sequenze di valori ordinate e immutabili.
<li><b>Insiemi</b>: sono gruppi non ordinati di valori.
<li><b>Dizionari</b>: sono gruppi non ordinati di coppie chiave-valore.
</ol>
<p>Naturalmente, esistono molti più tipi di questi. <a href=il-vostro-primo-programma-python.html#everythingisanobject>Ogni cosa è un oggetto</a> in Python, quindi ci sono anche tipi come <i>modulo</i>, <i>funzione</i>, <i>classe</i>, <i>metodo</i>, <i>file</i> e persino <i>codice compilato</i>. Ne avete già visti alcuni: <a href=il-vostro-primo-programma-python.html#runningscripts>i moduli hanno un nome</a>, <a href=il-vostro-primo-programma-python.html#docstrings>le funzioni sono dotate di una <code>docstring</code></a>, <i class=baa>&</i>c. Imparerete cosa sono le classi nel capitolo <a href=iteratori.html>Classi <i class=baa>&</i> iteratori</a> e cosa sono i file nel capitolo <a href=file.html>File</a>.
<p>Stringhe e byte sono abbastanza importanti — e abbastanza complicati — da essere trattati in un capitolo a parte. Diamo un’occhiata agli altri per primi.
<p class=a>⁂
<h2 id=booleans>Booleani</h2>
<aside>Potete usare virtualmente qualsiasi espressione in un contesto logico.</aside>
<p>I dati di tipo booleano sono veri o falsi. Python ha due costanti, chiamate ingegnosamente <code><dfn>True</dfn></code> e <code><dfn>False</dfn></code>, che possono essere usate per assegnare direttamente valori di tipo <dfn>booleano</dfn>. Anche le espressioni possono essere valutate come valori booleani. In certi posti (come le istruzioni <code>if</code>), Python si aspetta un’espressione da valutare come un valore booleano. Questi posti sono chiamati <i>contesti logici</i>. Potete virtualmente usare qualsiasi espressione in un contesto logico, e Python proverà a determinarne il valore di verità. Tipi di dato differenti hanno regole differenti per decidere se un loro valore è vero o falso in un contesto logico. (Questa frase avrà più senso una volta che avrete visto alcuni esempi concreti più avanti in questo capitolo.)
<p>Per esempio, considerate questo estratto da <a href=il-vostro-primo-programma-python.html#divingin><code>humansize.py</code></a>:
<pre class='nd pp'><code>if size < 0:
raise ValueError('il numero non deve essere negativo')</code></pre>
<p><var>size</var> è un intero, 0 è un intero, e <code><</code> è un operatore numerico. Il risultato dell’espressione <code>size < 0</code> è sempre un booleano. Potete verificarlo voi stessi nella shell interattiva di Python:
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>size = 1</kbd>
<samp class=p>>>> </samp><kbd class=pp>size < 0</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>size = 0</kbd>
<samp class=p>>>> </samp><kbd class=pp>size < 0</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>size = -1</kbd>
<samp class=p>>>> </samp><kbd class=pp>size < 0</kbd>
<samp class=pp>True</samp></pre>
<p>A causa di alcune questioni lasciate in eredità da Python 2, i booleani possono essere trattati come numeri. <code>True</code> vale <code>1</code> e <code>False</code> vale 0.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>True + True</kbd>
<samp class=pp>2</samp>
<samp class=p>>>> </samp><kbd class=pp>True - False</kbd>
<samp class=pp>1</samp>
<samp class=p>>>> </samp><kbd class=pp>True * False</kbd>
<samp class=pp>0</samp>
<samp class=p>>>> </samp><kbd class=pp>True / False</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: int division or modulo by zero</samp></pre>
<p>Ow, ow, ow! Non fatelo. Dimenticatevi persino che io lo abbia menzionato.
<p class=a>⁂
<h2 id=numbers>Numeri</h2>
<p>I numeri sono meravigliosi. Ce ne sono così tanti tra cui scegliere. Python supporta sia gli <dfn>interi</dfn> che i <dfn>numeri in virgola mobile</dfn>. Non c’è alcuna dichiarazione di tipo per distinguerli, perché Python è in grado di farlo grazie alla presenza o meno del punto <dfn>decimale</dfn>.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>type(1)</kbd> <span class=u>①</span></a>
<samp><class 'int'></samp>
<a><samp class=p>>>> </samp><kbd class=pp>isinstance(1, int)</kbd> <span class=u>②</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>1 + 1</kbd> <span class=u>③</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>1 + 1.0</kbd> <span class=u>④</span></a>
<samp class=pp>2.0</samp>
<samp class=p>>>> </samp><kbd class=pp>type(2.0)</kbd>
<samp><class 'float'></samp></pre>
<ol>
<li>Potete usare la funzione <code>type()</code> per controllare il tipo di qualsiasi valore o variabile. Come vi sareste aspettati, <code>1</code> è un <code>int</code>.
<li>Similmente, potete usare la funzione <code>isinstance()</code> per controllare se un valore o una variabile è di un certo tipo.
<li>Aggiungere un <code>int</code> a un <code>int</code> dà come risultato un <code>int</code>.
<li>Aggiungere un <code>int</code> a un <code>float</code> dà come risultato un <code>float</code>. Python converte implicitamente l’<code>int</code> in un <code>float</code> per eseguire l’addizione, poi restituisce un <code>float</code> come risultato.
</ol>
<h3 id=number-coercion>Convertire interi in reali e viceversa</h3>
<p>Come avete appena visto, alcuni operatori (come l’addizione) convertono implicitamente gli interi in numeri in virgola mobile su necessità. Potete anche convertirli esplicitamente voi stessi.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>float(2)</kbd> <span class=u>①</span></a>
<samp class=pp>2.0</samp>
<a><samp class=p>>>> </samp><kbd class=pp>int(2.0)</kbd> <span class=u>②</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>int(2.5)</kbd> <span class=u>③</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>int(-2.5)</kbd> <span class=u>④</span></a>
<samp class=pp>-2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>1.12345678901234567890</kbd> <span class=u>⑤</span></a>
<samp class=pp>1.1234567890123457</samp>
<a><samp class=p>>>> </samp><kbd class=pp>type(1000000000000000)</kbd> <span class=u>⑥</span></a>
<samp><class 'int'></samp></pre>
<ol>
<li>Potete convertire esplicitamente un <code>int</code> in un <code>float</code> chiamando la funzione <code>float()</code>.
<li>Naturalmente, potete anche convertire esplicitamente un <code>float</code> in un <code>int</code> chiamando <code>int()</code>.
<li>La funzione <code>int()</code> esegue un troncamento, non un arrotondamento.
<li>La funzione <code>int()</code> tronca i numeri negativi verso lo 0. È una vera funzione di troncamento, non una funzione di parte intera.
<li>I numeri in virgola mobile sono accurati fino a 15 decimali.
<li>Gli interi possono essere arbitrariamente grandi.
</ol>
<blockquote class='note compare python2'>
<p><span class=u>☞</span>Python 2 era dotato di tipi separati per <code>int</code> e <code>long</code>. Il tipo di dato <code>int</code> era limitato da <code>sys.maxint</code>, che variava a seconda della piattaforma ma di solito valeva <code>2<sup>32</sup>-1</code>. Python 3 possiede un solo tipo per i numeri interi, che si comporta quasi sempre come il vecchio tipo <code>long</code> di Python 2. Si veda la <a href=http://www.python.org/dev/peps/pep-0237><abbr>PEP</abbr> 237</a> per i dettagli.
</blockquote>
<h3 id=common-numerical-operations>Operazioni comuni sui numeri</h3>
<p>Potete fare ogni tipo di operazione con i numeri.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>11 / 2</kbd> <span class=u>①</span></a>
<samp class=pp>5.5</samp>
<a><samp class=p>>>> </samp><kbd class=pp>11 // 2</kbd> <span class=u>②</span></a>
<samp class=pp>5</samp>
<a><samp class=p>>>> </samp><kbd class=pp>−11 // 2</kbd> <span class=u>③</span></a>
<samp class=pp>−6</samp>
<a><samp class=p>>>> </samp><kbd class=pp>11.0 // 2</kbd> <span class=u>④</span></a>
<samp class=pp>5.0</samp>
<a><samp class=p>>>> </samp><kbd class=pp>11 ** 2</kbd> <span class=u>⑤</span></a>
<samp class=pp>121</samp>
<a><samp class=p>>>> </samp><kbd class=pp>11 % 2</kbd> <span class=u>⑥</span></a>
<samp class=pp>1</samp>
</pre>
<ol>
<li>L’operatore <code>/</code> esegue la divisione in virgola mobile. Restituisce un <code>float</code> anche quando il numeratore e il denominatore sono entrambi numeri di tipo <code>int</code>.
<li>L’operatore <code>//</code> esegue un tipo strambo di divisione tra interi. Quando il risultato è positivo, potete immaginarla come un troncamento (non un arrotondamento) a 0 decimali, ma fate attenzione.
<li>Quando eseguite la divisione intera tra numeri negativi, l’operatore <code>//</code> arrotonda “per eccesso” verso l’intero più vicino. Matematicamente parlando, l’arrotondamento è “per difetto” dato che <code>−6</code> è inferiore a <code>−5</code>, ma se vi aspettate un troncamento a <code>−5</code> potreste essere indotti in errore.
<li>L’operatore <code>//</code> non restituisce sempre un intero. Se il numeratore o il denominatore sono di tipo <code>float</code>, effettuerà un arrontondamento all’intero più vicino, ma l’effettivo valore di ritorno sarà un <code>float</code>.
<li>L’operatore <code>**</code> significa “elevato alla potenza di”. <code>11<sup>2</sup></code> vale <code>121</code>.
<li>L’operatore <code>%</code> dà il resto dopo aver effettuato una divisione di tipo intero. <code>11</code> diviso per <code>2</code> vale <code>5</code> con il resto di <code>1</code>, quindi il risultato in questo caso è <code>1</code>.
</ol>
<blockquote class='note compare python2'>
<p><span class=u>☞</span>In Python 2, l’operatore <code>/</code> normalmente effettuava una divisione di tipo intero, ma avreste potuto obbligarlo a comportarsi come la divisione in virgola mobile includendo una speciale direttiva nel vostro codice. In Python 3, l’operatore <code>/</code> effettua sempre una divisione in virgola mobile. Si veda la <a href=http://www.python.org/dev/peps/pep-0238/><abbr>PEP</abbr> 238</a> per i dettagli.
</blockquote>
<h3 id=fractions>Frazioni</h3>
<p>Python non si limita agli interi e ai numeri in virgola mobile. Può anche fare tutta quella matematica elaborata che avete imparato alle superiori e poi prontamente dimenticato.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>import fractions</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>x = fractions.Fraction(1, 3)</kbd> <span class=u>②</span></a>
<samp class=p>>>> </samp><kbd class=pp>x</kbd>
<samp class=pp>Fraction(1, 3)</samp>
<a><samp class=p>>>> </samp><kbd class=pp>x * 2</kbd> <span class=u>③</span></a>
<samp class=pp>Fraction(2, 3)</samp>
<a><samp class=p>>>> </samp><kbd class=pp>fractions.Fraction(6, 4)</kbd> <span class=u>④</span></a>
<samp class=pp>Fraction(3, 2)</samp>
<a><samp class=p>>>> </samp><kbd class=pp>fractions.Fraction(0, 0)</kbd> <span class=u>⑤</span></a>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "fractions.py", line 96, in __new__
raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
ZeroDivisionError: Fraction(0, 0)</samp></pre>
<ol>
<li>Per cominciare a usare le frazioni, importate il modulo <code>fractions</code>.
<li>Per definire una frazione, create un oggetto <code>Fraction</code> e passategli il numeratore e il denominatore.
<li>Potete eseguire tutte le comuni operazioni matematiche sulle frazioni. Le operazioni restituiscono un nuovo oggetto <code>Fraction</code>. <code>2 * (1/3) = (2/3)</code>
<li>L’oggetto <code>Fraction</code> semplificherà le frazioni automaticamente. <code>(6/4) = (3/2)</code>
<li>Python ha il buon senso di non creare frazioni con denominatore uguale a zero.
</ol>
<h3 id=trig>Trigonometria</h3>
<p>Potete anche operare con la trigonometria di base in Python.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>import math</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>math.pi</kbd> <span class=u>①</span></a>
<samp class=pp>3.1415926535897931</samp>
<a><samp class=p>>>> </samp><kbd class=pp>math.sin(math.pi / 2)</kbd> <span class=u>②</span></a>
<samp class=pp>1.0</samp>
<a><samp class=p>>>> </samp><kbd class=pp>math.tan(math.pi / 4)</kbd> <span class=u>③</span></a>
<samp class=pp>0.99999999999999989</samp></pre>
<ol>
<li>Il modulo <code>math</code> include una costante per π, il rapporto tra la circonferenza di un cerchio e il suo diametro.
<li>Il modulo <code>math</code> contiene tutte le funzioni trigonometriche di base, comprese <code>sin()</code>, <code>cos()</code>, <code>tan()</code> e varianti come <code>asin()</code>.
<li>Notate, comunque, che la precisione numerica di Python non è infinita. <code>tan(π / 4)</code> dovrebbe restituire <code>1.0</code>, non <code>0.99999999999999989</code>.
</ol>
<h3 id=numbers-in-a-boolean-context>Numeri in un contesto logico</h3>
<aside>I valori uguali a zero sono falsi e i valori diversi da zero sono veri.</aside>
<p>Potete usare i numeri <a href=#booleans>in un contesto logico</a> come quello di un’istruzione <code>if</code>. I valori uguali a zero sono falsi e i valori diversi da zero sono veri.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd> <span class=u>①</span></a>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(1)</kbd> <span class=u>②</span></a>
<samp>sì, è vero</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(-1)</kbd>
<samp>sì, è vero</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(0)</kbd>
<samp>no, è falso</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(0.1)</kbd> <span class=u>③</span></a>
<samp>sì, è vero</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(0.0)</kbd>
<samp>no, è falso</samp>
<samp class=p>>>> </samp><kbd class=pp>import fractions</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(fractions.Fraction(1, 2))</kbd> <span class=u>④</span></a>
<samp>sì, è vero</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(fractions.Fraction(0, 1))</kbd>
<samp>no, è falso</samp></pre>
<ol>
<li>Sapevate di poter definire le vostre funzioni nella shell interattiva di Python? Vi basta premere <kbd>INVIO</kbd> alla fine di ogni riga, e <kbd>INVIO</kbd> su una riga vuota per concludere la definizione.
<li>In un contesto logico, gli interi diversi da zero sono veri e 0 è falso.
<li>I numeri in virgola mobile diversi da zero sono veri e <code>0.0</code> è falso. Fate attenzione! Se c’è anche il più piccolo errore di arrotondamento (non impossibile, come avete visto nella sezione precedente) allora Python opererà su <code>0.0000000000001</code> invece di 0 e restituirà <code>True</code>.
<li>Anche le frazioni possono essere usate in un contesto logico. <code>Fraction(0, n)</code> è falso per tutti i valori di <var>n</var>. Tutte le altre frazioni sono vere.
</ol>
<p class=a>⁂
<h2 id=lists>Liste</h2>
<p>Le liste sono il mulo da soma dei tipi di dato Python. Quando dico “<dfn>lista</dfn>” potreste pensare a un “array la cui dimensione devo dichiarare in anticipo e che può solo contenere elementi di uno stesso tipo, <i class=baa>&</i>c”. Non pensatelo. Le liste sono molto più fighe di così.
<blockquote class='note compare perl5'>
<p><span class=u>☞</span>Una lista in Python è come un array in Perl 5. In Perl 5, le variabili che memorizzano un array cominciano sempre con il carattere <code>@</code>; in Python, le variabili possono essere chiamate in qualsiasi modo, e Python tiene traccia del tipo di dato internamente.
</blockquote>
<blockquote class='note compare java'>
<p><span class=u>☞</span>Una lista in Python è molto più di un array in Java (anche se può essere usata come tale, se questo è tutto quello che volete dalla vita). Un’analogia migliore sarebbe quella con la classe <code>ArrayList</code>, che può contenere oggetti di tipo arbitrario e può espandersi dinamicamente man mano che nuovi elementi vengono aggiunti.
</blockquote>
<h3 id=creatinglists>Creare una lista</h3>
<p>Creare una lista è facile: usate le parentesi quadre per racchiudere un elenco di valori separati da virgole.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'mpilgrim', 'z', 'esempio']</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'b', 'mpilgrim', 'z', 'esempio']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[0]</kbd> <span class=u>②</span></a>
<samp class=pp>'a'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[4]</kbd> <span class=u>③</span></a>
<samp class=pp>'esempio'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[-1]</kbd> <span class=u>④</span></a>
<samp class=pp>'esempio'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[-3]</kbd> <span class=u>⑤</span></a>
<samp class=pp>'mpilgrim'</samp></pre>
<ol>
<li>Per prima cosa, definite una lista di cinque elementi. Notate che essi mantengono il loro ordine originale. Questo non è un caso, poiché una lista è un insieme ordinato di elementi.
<li>Una lista può essere usata come un array il cui indice parte da zero. Il primo elemento di una lista non vuota è sempre <code>a_list[0]</code>.
<li>L’ultimo elemento di questa lista di cinque elementi è <code>a_list[4]</code>, perché l’indice delle liste parte sempre da zero.
<li>Un indice negativo accede agli elementi a partire dalla fine della lista, contando all’indietro. L’ultimo elemento di una lista non vuota è sempre <code>a_list[-1]</code>.
<li>Se l’indice negativo vi confonde, pensatela in questo modo: <code>a_list[-<var>n</var>] == a_list[len(a_list) - <var>n</var>]</code>. Quindi, in questa lista, <code>a_list[-3] == a_list[5 - 3] == a_list[2]</code>.
</ol>
<h3 id=slicinglists>Affettare una lista</h3>
<aside>a_list[0] è il primo elemento di a_list.</aside>
<p>Una volta che avete definito una lista, potete ottenerne una parte qualsiasi sotto forma di una nuova lista. Questa operazione si chiama <i>affettare</i> la lista.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'b', 'mpilgrim', 'z', 'esempio']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[1:3]</kbd> <span class=u>①</span></a>
<samp class=pp>['b', 'mpilgrim']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[1:-1]</kbd> <span class=u>②</span></a>
<samp class=pp>['b', 'mpilgrim', 'z']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[0:3]</kbd> <span class=u>③</span></a>
<samp class=pp>['a', 'b', 'mpilgrim']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[:3]</kbd> <span class=u>④</span></a>
<samp class=pp>['a', 'b', 'mpilgrim']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[3:]</kbd> <span class=u>⑤</span></a>
<samp class=pp>['z', 'esempio']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[:]</kbd> <span class=u>⑥</span></a>
<samp class=pp>['a', 'b', 'mpilgrim', 'z', 'esempio']</samp></pre>
<ol>
<li>Potete ottenere una parte di una lista, chiamata “fetta”, specificando due indici. Il valore di ritorno è una nuova lista che contiene tutti gli elementi della lista, in ordine, a cominciare dal primo indice della fetta (in questo caso <code>a_list[1]</code>) fino al secondo indice della fetta escluso (in questo caso <code>a_list[3]</code>).
<li>L’affettatura di una lista funziona anche se uno o entrambi gli indici della fetta sono negativi. Se vi è d’aiuto, potete pensarla in questo modo: leggendo la lista da sinistra a destra, il primo indice della fetta indica il primo elemento che volete, e il secondo indice della fetta indica il primo elemento che non volete. Il valore di ritorno è tutto quello che sta in mezzo.
<li>L’indice delle liste comincia da zero, quindi <code>a_list[0:3]</code> restituisce i primi tre elementi della lista, cominciando da <code>a_list[0]</code> fino a <code>a_list[3]</code> escluso.
<li>Se l’indice sinistro della fetta è 0, potete ometterlo e 0 diventa implicito. Quindi <code>a_list[:3]</code> è la stessa cosa di <code>a_list[0:3]</code>, perché lo 0 iniziale è implicito.
<li>Similmente, se l’indice destro della fetta è la lunghezza della lista, potete ometterlo. Quindi <code>a_list[3:]</code> è la stessa cosa di <code>a_list[3:5]</code>, perché questa lista ha cinque elementi. C’è una piacevole simmetria qui. In questa lista di cinque elementi, <code>a_list[:3]</code> restituisce i primi 3 elementi e <code>a_list[3:]</code> restituisce gli ultimi due elementi. In effetti, <code>a_list[:<var>n</var>]</code> restituirà sempre i primi <var>n</var> elementi e <code>a_list[<var>n</var>:]</code> restituirà il resto, a prescindere dalla lunghezza della lista.
<li>Se entrambi gli indici della fetta vengono omessi, tutti gli elementi della lista vengono inclusi. Ma questa non è la stessa lista della variabile <var>a_list</var> originale. È una nuova lista a cui capita di avere tutti gli stessi elementi. <code>a_list[:]</code> è una notazione abbreviata per creare la copia completa di una lista.
</ol>
<h3 id=extendinglists>Aggiungere elementi a una lista</h3>
<p>Ci sono quattro modi per aggiungere un elemento a una lista.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a']</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_list = a_list + [2.0, 3]</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>a_list</kbd> <span class=u>②</span></a>
<samp class=pp>['a', 2.0, 3]</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.append(True)</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 2.0, 3, True]</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.extend(['quattro', 'Ω'])</kbd> <span class=u>④</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 2.0, 3, True, 'quattro', 'Ω']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.insert(0, 'Ω')</kbd> <span class=u>⑤</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['Ω', 'a', 2.0, 3, True, 'quattro', 'Ω']</samp></pre>
<ol>
<li>L’operatore <code>+</code> concatena liste per creare una nuova lista. Una lista può contenere qualsiasi numero di elementi, in quanto non c’è alcun limite sulle dimensioni (a parte la memoria disponibile). Tuttavia, se la memoria è un problema, sappiate che la concatenazione tra liste crea una seconda lista in memoria. In questo caso, quella nuova lista viene immediatamente assegnata alla variabile <var>a_list</var> esistente. Quindi, questa riga di codice in realtà è un’operazione composta da due passi — concatenazione e poi assegnamento — che potrebbe (temporaneamente) consumare molta memoria quando avete a che fare con liste di grandi dimensioni.
<li>Una lista può contenere elementi di ogni tipo di dato e gli elementi contenuti in una singola lista non devono per forza essere tutti dello stesso tipo. Qui abbiamo una lista contenente una stringa, un numero in virgola mobile e un intero.
<li>Il metodo <code>append()</code> aggiunge un singolo elemento alla fine di una lista. (Ora abbiamo <em>quattro</em> tipi di dato differenti nella lista!)
<li>Le liste sono implementate come classi. “Creare” una lista vuol dire in realtà istanziare una classe. Come tale, una lista è dotata di metodi che operano su di essa. Il metodo <code>extend()</code> prende una lista come unico argomento e aggiunge ognuno degli elementi dell’argomento in coda alla lista originale.
<li>Il metodo <code>insert()</code> inserisce un singolo elemento in una lista. Il primo argomento è l’indice del primo elemento nella lista che verrà spostato dalla sua posizione. Gli elementi di una lista non devono essere unici; per esempio, ora ci sono due elementi diversi con il valore <code>'a'</code>, <code>a_list[0]</code> e <code>a_list[1]</code>.
</ol>
<blockquote class='note compare perl'>
<p><span class=u>☞</span><code><var>a_list</var>.insert(0, <var>valore</var>)</code> ha lo stesso effetto della funzione <code>unshift()</code> in Perl. Aggiunge un elemento all’inizio della lista e incrementa l’indice posizionale di tutti gli altri elementi per fare spazio.
</blockquote>
<p>Diamo un’occhiata più da vicino alle differenze tra <code>append()</code> ed <code>extend()</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'c']</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.extend(['d', 'e', 'f'])</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'b', 'c', 'd', 'e', 'f']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>len(a_list)</kbd> <span class=u>②</span></a>
<samp class=pp>6</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list[-1]</kbd>
<samp class=pp>'f'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.append(['g', 'h', 'i'])</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']]</samp>
<a><samp class=p>>>> </samp><kbd class=pp>len(a_list)</kbd> <span class=u>④</span></a>
<samp class=pp>7</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list[-1]</kbd>
<samp class=pp>['g', 'h', 'i']</samp></pre>
<ol>
<li>Il metodo <code>extend()</code> prende un singolo argomento, che è sempre una lista, e aggiunge ogni elemento di quella lista ad <var>a_list</var>.
<li>Se cominciate con una lista di tre elementi e la estendete con una lista di altri tre elementi, terminerete con una lista di sei elementi.
<li>D’altra parte, il metodo <code>append()</code> prende un singolo argomento, che può avere un tipo di dato qualsiasi. Qui, state chiamando il metodo <code>append()</code> con una lista di tre elementi.
<li>Se cominciate con una lista di sei elementi e vi accodate una lista, terminerete con... una lista di sette elementi. Perché sette? Perché l’ultimo elemento (che avete appena aggiunto) <em>è anch’esso una lista</em>. Le liste possono contenere ogni tipo di dato, comprese altre liste. Questo potrebbe essere quello che desiderate, oppure no. Ma è quello che avete chiesto, ed è quello che avete ottenuto.
</ol>
<h3 id=searchinglists>Cercare valori in una lista</h3>
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'nuovo', 'mpilgrim', 'nuovo']</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.count('nuovo')</kbd> <span class=u>①</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>'nuovo' in a_list</kbd> <span class=u>②</span></a>
<samp class=pp>True</samp>
<samp class=p>>>> </samp><kbd class=pp>'c' in a_list</kbd>
<samp class=pp>False</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.index('mpilgrim')</kbd> <span class=u>③</span></a>
<samp class=pp>3</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.index('nuovo')</kbd> <span class=u>④</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.index('c')</kbd> <span class=u>⑤</span></a>
<samp class=traceback>Traceback (innermost last):
File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list</samp></pre>
<ol>
<li>Come potreste aspettarvi, il metodo <code>count()</code> restituisce il numero di occorrenze di uno specifico valore in una lista.
<li>Nel caso tutto quello che vogliate sapere sia se un valore è presente nella lista oppure no, l’operatore <code>in</code> è leggermente più veloce rispetto al metodo <code>count()</code>. L’operatore <code>in</code> restituisce sempre <code>True</code> o <code>False</code>, senza dirvi quante volte il valore compare nella lista.
<li>Né l’operatore <code>in</code> né il metodo <code>count()</code> vi diranno <em>dove</em> si trova il valore. Se avete bisogno di questa informazione, chiamate il metodo <code>index()</code>. Per default questo metodo cercherà nell’intera lista, anche se potete specificare come secondo argomento opzionale l’indice (a partire da 0) da cui cominciare, e come terzo argomento opzionale persino l’indice (a partire da 0) in cui terminare la ricerca.
<li>Il metodo <code>index()</code> trova la <em>prima</em> occorrenza di un valore nella lista. In questo caso, <code>'nuovo'</code> appare due volte nella lista, in <code>a_list[2]</code> e <code>a_list[4]</code>, ma il metodo <code>index()</code> restituirà solamente l’indice della prima occorrenza.
<li>Come <em>non</em> vi sareste aspettati, se il valore non viene trovato nella lista il metodo <code>index()</code> solleverà un’eccezione.
</ol>
<p>Siete sorpresi? Ma è così: il metodo <code>index()</code> solleva un’eccezione se non trova il valore nella lista. Questa è una differenza considerevole rispetto alla maggior parte dei linguaggi, che resituiscono un qualche indice non valido (come <code>-1</code>). Sebbene questo possa sembrare fastidioso all’inizio, penso che finirete per apprezzarlo. Significa che il vostro programma fallirà alla sorgente del problema invece di fallire stranamente e silenziosamente più tardi. Ricordate, <a href=#creatinglists><code>-1</code> è un indice di lista valido</a>. Se il metodo <code>index()</code> restituisse <code>-1</code>, questo potrebbe condurre ad alcune sessioni di debug non esattamente divertenti!
<h3 id=removingfromlists>Rimuovere elementi da una lista</h3>
<aside>Le liste non hanno mai buchi.</aside>
<p>Le liste possono espandersi e contrarsi automaticamente. Finora avete visto la parte relativa all’espansione. Esistono anche diversi modi per rimuovere elementi da una lista.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'nuovo', 'mpilgrim', 'nuovo']</kbd>
<samp class=p>>>> </samp><kbd class=pp>a_list[1]</kbd>
<samp class=pp>'b'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>del a_list[1]</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'nuovo', 'mpilgrim', 'nuovo']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list[1]</kbd> <span class=u>②</span></a>
<samp class=pp>'nuovo'</samp></pre>
<ol>
<li>Potete usare l’istruzione <code><dfn>del</dfn></code> per cancellare uno specifico elemento da una lista.
<li>Accedere all’elemento di indice <code>1</code> dopo aver cancellato l’elemento di indice <code>1</code> <em>non</em> risulta in un errore. L’indice posizionale di tutti gli elementi che seguono l’elemento rimosso verrà spostato per “riempire il buco” lasciato dalla cancellazione dell’elemento.
</ol>
<p>Non conoscete l’indice posizionale? Non è un problema, perché potete anche rimuovere gli elementi tramite il loro valore.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.remove('nuovo')</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'mpilgrim', 'nuovo']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.remove('nuovo')</kbd> <span class=u>②</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'mpilgrim']</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list.remove('nuovo')</kbd>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list</samp></pre>
<ol>
<li>Potete anche rimuovere un elemento da una lista con il metodo <code>remove()</code>. Il metodo <code>remove()</code> prende un <em>valore</em> e rimuove la prima occorrenza di quel valore dalla lista. Ancora una volta, l’indice posizionale di tutti gli elementi che seguono l’elemento cancellato verrà diminuito per “riempire il buco”. Le liste non hanno mai buchi.
<li>Potete chiamare il metodo <code>remove()</code> tutte le volte che volete, ma verrà sollevata un’eccezione se provate a rimuovere un valore che non è presente nella lista.
</ol>
<h3 id=popgoestheweasel>Rimuovere elementi da una lista: giro bonus</h3>
<p>Un altro metodo interessante delle liste è <code>pop()</code>. Il metodo <code>pop()</code> rappresenta ancora un altro modo di <a href=#removingfromlists>rimuovere elementi da una lista</a>, ma con una peculiarità.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'nuovo', 'mpilgrim']</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.pop()</kbd> <span class=u>①</span></a>
<samp class=pp>'mpilgrim'</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'b', 'nuovo']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.pop(1)</kbd> <span class=u>②</span></a>
<samp class=pp>'b'</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list</kbd>
<samp class=pp>['a', 'nuovo']</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list.pop()</kbd>
<samp class=pp>'nuovo'</samp>
<samp class=p>>>> </samp><kbd class=pp>a_list.pop()</kbd>
<samp class=pp>'a'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list.pop()</kbd> <span class=u>③</span></a>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop from empty list</samp></pre>
<ol>
<li>Quando viene invocato senza argomenti, il metodo <code>pop()</code> delle liste rimuove l’ultimo elemento nella lista <em>e restituisce il valore che ha rimosso</em>.
<li>Potete rimuovere elementi arbitrari da una lista passando un indice posizionale al metodo <code>pop()</code>. Il metodo rimuoverà quell’elemento, sposterà tutti gli elementi seguenti per “riempire il buco” e restituirà il valore che ha rimosso.
<li>Invocare <code>pop()</code> su una lista vuota solleva un’eccezione.
</ol>
<blockquote class='note compare perl'>
<p><span class=u>☞</span>Chiamare il metodo <code>pop()</code> delle liste senza un argomento ha lo stesso effetto della funzione <code>pop()</code> in Perl: rimuove l’ultimo elemento da una lista e restituisce il valore dell’elemento rimosso. Perl possiede un’altra funzione, <code>shift()</code>, che rimuove il primo elemento e restituisce il suo valore; in Python, questa operazione è equivalente a <code><var>a_list</var>.pop(0)</code>.
</blockquote>
<h3 id=lists-in-a-boolean-context>Liste in un contesto logico</h3>
<aside>Le liste vuote sono false; tutte le altre liste sono vere.</aside>
<p>Potete usare una lista anche in <a href=#booleans>un contesto logico</a> come quello di un’istruzione <code>if</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true([])</kbd> <span class=u>①</span></a>
<samp>no, è falso</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(['a'])</kbd> <span class=u>②</span></a>
<samp>sì, è vero</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true([False])</kbd> <span class=u>③</span></a>
<samp>sì, è vero</samp></pre>
<ol>
<li>In un contesto logico, una lista vuota è falsa.
<li>Qualsiasi lista con almeno un elemento è vera.
<li>Qualsiasi lista con almeno un elemento è vera. Il valore degli elementi è irrilevante.
</ol>
<p class=a>⁂
<h2 id=tuples>Tuple</h2>
<p>Una <dfn>tupla</dfn> è una lista immutabile. Una tupla non può essere modificata in alcun modo dopo che è stata creata.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple = ("a", "b", "mpilgrim", "z", "esempio")</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_tuple</kbd>
<samp class=pp>('a', 'b', 'mpilgrim', 'z', 'esempio')</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple[0]</kbd> <span class=u>②</span></a>
<samp class=pp>'a'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple[-1]</kbd> <span class=u>③</span></a>
<samp class=pp>'esempio'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple[1:3]</kbd> <span class=u>④</span></a>
<samp class=pp>('b', 'mpilgrim')</samp></pre>
<ol>
<li>Una tupla si definisce nello stesso modo di una lista, a parte il fatto che l’intero insieme di elementi è racchiuso tra parentesi tonde anziché parentesi quadre.
<li>Gli elementi di una tupla hanno un ordine definito, esattamente come in una lista. Gli indici di una tupla partono da zero, esattamente come in una lista, quindi il primo elemento di una tupla non vuota è sempre <code>a_tuple[0]</code>.
<li>Gli indici negativi partono dalla fine della tupla, esattamente come in una lista.
<li>Anche l’affettatura funziona esattamente come per una lista. Quando affettate una lista, ottenete una nuova lista; quando affettate una tupla, ottenete una nuova tupla.
</ol>
<p>La differenza principale tra tuple e liste è che le tuple non possono essere modificate. In termini tecnici, le tuple sono <dfn>immutabili</dfn>. In termini pratici, non sono dotate di alcun metodo che vi permetterebbe di modificarle. Le liste hanno metodi come <code>append()</code>, <code>extend()</code>, <code>insert()</code>, <code>remove()</code> e <code>pop()</code>. Le tuple sono prive di tutti questi metodi. Potete affettare una tupla (perché questa operazione crea una nuova tupla) e potete controllare se una tupla contiene un particolare valore (perché questa operazione non modifica la tupla) e… questo è tutto.
<pre class=screen>
# continua dall'esempio precedente
<samp class=p>>>> </samp><kbd class=pp>a_tuple</kbd>
<samp class=pp>('a', 'b', 'mpilgrim', 'z', 'esempio')</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple.append("nuovo")</kbd> <span class=u>①</span></a>
<samp class=traceback>Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'append'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple.remove("z")</kbd> <span class=u>②</span></a>
<samp class=traceback>Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'remove'</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_tuple.index("esempio")</kbd> <span class=u>③</span></a>
<samp class=pp>4</samp>
<a><samp class=p>>>> </samp><kbd class=pp>"z" in a_tuple</kbd> <span class=u>④</span></a>
<samp class=pp>True</samp></pre>
<ol>
<li>Non potete aggiungere elementi a una tupla. Le tuple non hanno alcun metodo <code>append()</code> o <code>extend()</code>.
<li>Non potete rimuovere elementi da una tupla. Le tuple non hanno alcun metodo <code>remove()</code> o <code>pop()</code>.
<li><em>Potete</em> cercare elementi in una tupla, dato che questa operazione non modifica la tupla.
<li>Potete anche usare l’operatore <code>in</code> per controllare se un elemento è presente nella tupla.
</ol>
<p>Quindi a cosa servono le tuple?
<ul>
<li>Le tuple sono più veloci delle liste. Se state definendo un insieme di valori costante e tutto quello per cui lo userete è iterare attraverso i suoi elementi, usate una tupla invece di una lista.
<li>Il vostro codice sarà più sicuro se “proteggete dalla scrittura” i dati che non hanno bisogno di essere modificati. Usare una tupla invece di una lista è come avere un’istruzione <code>assert</code> implicita che mostra che questi dati sono costanti e che è necessario ricorrere a un ragionamento particolare (e a una funzione particolare) per eludere questo vincolo.
<li>Alcune tuple possono essere usate come chiavi di un dizionario (nello specifico, tuple che contengono valori <i>immutabili</i> come stringhe, numeri e altre tuple). Le liste non possono mai essere usate come chiavi di un dizionario, perché le liste non sono immutabili.
</ul>
<blockquote class=note>
<p><span class=u>☞</span>Le tuple possono essere convertite in liste e viceversa. La funzione predefinita <code>tuple()</code> accetta una lista e restituisce una tupla con gli stessi elementi; la funzione <code>list()</code> accetta una tupla e restituisce una lista. In effetti, <code>tuple()</code> congela una lista e <code>list()</code> scongela una tupla.
</blockquote>
<h3 id=tuples-in-a-boolean-context>Tuple in un contesto logico</h3>
<p>Potete usare le tuple in <a href=#booleans>un contesto logico</a> come quello di un’istruzione <code>if</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(())</kbd> <span class=u>①</span></a>
<samp>no, è falso</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(('a', 'b'))</kbd> <span class=u>②</span></a>
<samp>sì, è vero</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true((False,))</kbd> <span class=u>③</span></a>
<samp>sì, è vero</samp>
<a><samp class=p>>>> </samp><kbd class=pp>type((False))</kbd> <span class=u>④</span></a>
<samp><class 'bool'></samp>
<samp class=p>>>> </samp><kbd class=pp>type((False,))</kbd>
<samp><class 'tuple'></samp></pre>
<ol>
<li>In un contesto logico, una tupla vuota è falsa.
<li>Qualsiasi tupla con almeno un elemento è vera.
<li>Qualsiasi tupla con almeno un elemento è vera. Il valore degli elementi è irrilevante. Ma cosa ci fa lì quella virgola?
<li>Per creare una tupla di un elemento, dovete inserire una virgola dopo il valore. Senza la virgola, Python presume che abbiate semplicemente inserito una coppia aggiuntiva di parentesi, che è innocua ma non crea una tupla.
</ol>
<h3 id=multivar>Assegnare più di un valore alla volta</h3>
<p>Ecco una fantastica scorciatioia di programmazione: in Python, potete usare una tupla per assegnare più di un valore alla volta.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>v = ('a', 2, True)</kbd>
<a><samp class=p>>>> </samp><kbd>(x, y, z) = v</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>x</kbd>
<samp class=pp>'a'</samp>
<samp class=p>>>> </samp><kbd class=pp>y</kbd>
<samp class=pp>2</samp>
<samp class=p>>>> </samp><kbd class=pp>z</kbd>
<samp class=pp>True</samp></pre>
<ol>
<li><var>v</var> è una tupla di tre elementi e <code>(x, y, z)</code> è una tupla di tre variabili. Assegnare l’una all’altra assegna ognuno dei valori di <var>v</var> a ognuna delle variabili, in ordine.
</ol>
<p>Questa scorciatoia può essere usata in tutti i modi. Supponete di voler assegnare nomi a un intervallo di valori. Potete usare la funzione predefinita <code>range()</code> con l’assegnamento multivariabile per assegnare velocemente valori consecutivi.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>MONDAY</kbd> <span class=u>②</span></a>
<samp class=pp>0</samp>
<samp class=p>>>> </samp><kbd class=pp>TUESDAY</kbd>
<samp class=pp>1</samp>
<samp class=p>>>> </samp><kbd class=pp>SUNDAY</kbd>
<samp class=pp>6</samp></pre>
<ol>
<li>La funzione predefinita <code>range()</code> costruisce una sequenza di interi. (Tecnicamente, la funzione <code>range()</code> restuitsce un <a href=iteratori.html>iteratore</a>, non una lista di tuple, ma imparerete la distinzione più avanti.) <var>MONDAY</var>, <var>TUESDAY</var>, <var>WEDNESDAY</var>, <var>THURSDAY</var>, <var>FRIDAY</var>, <var>SATURDAY</var> e <var>SUNDAY</var> sono le variabili che state definendo. (Questo esempio proviene dal modulo <code>calendar</code>, un piccolo modulo divertente che stampa calendari, come il programma <abbr>UNIX</abbr> <code>cal</code>. Il modulo <code>calendar</code> definisce costanti intere per i giorni della settimana.)
<li>Ora ogni variabile ha il suo valore: <var>MONDAY</var> vale 0, <var>TUESDAY</var> vale <code>1</code>, e così via.
</ol>
<p>Potete anche usare l’assegnamento multivariabile per costruire funzioni che restituiscono più di un valore, semplicemente restituendo una tupla di tutti i valori. Il chiamante può trattarla come una singola tupla, oppure può assegnare i valori a singole variabili. Molte librerie Python standard lo fanno, incluso il modulo <code>os</code> che vedrete nel <a href=descrizioni.html#os>prossimo capitolo</a>.
<p class=a>⁂
<h2 id=sets>Insiemi</h2>
<p>Un <dfn>insieme</dfn> è un “gruppo” non ordinato di valori unici. Un singolo insieme può contenere valori di qualsiasi tipo di dato immutabile. Una volta che avete due insiemi, potete effettuare le classiche operazioni sugli insiemi come l’unione, l’intersezione e la differenza tra insiemi.
<h3 id=creating-a-set>Creare un insieme</h3>
<p>Cominciamo dall’inizio. Creare un insieme è facile.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_set = {1}</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>type(a_set)</kbd> <span class=u>②</span></a>
<samp><class 'set'></samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set = {1, 2}</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2}</samp></pre>
<ol>
<li>Per creare un insieme con un valore, mettete il valore tra parentesi graffe (<code>{}</code>).
<li>Gli insiemi sono effettivamente implementati come <a href=iteratori.html#defining-classes>classi</a>, ma non preoccupatevi di questo per ora.
<li>Per creare un insieme con più valori, separate i valori con virgole e circondate il tutto con parentesi graffe.
</ol>
<p>Potete anche creare un insieme a partire da una <a href=#lists>lista</a>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_list = ['a', 'b', 'mpilgrim', True, False, 42]</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_set = set(a_list)</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>a_set</kbd> <span class=u>②</span></a>
<samp class=pp>{'a', False, 'b', True, 'mpilgrim', 42}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_list</kbd> <span class=u>③</span></a>
<samp class=pp>['a', 'b', 'mpilgrim', True, False, 42]</samp></pre>
<ol>
<li>Per creare un insieme da una lista, usate la funzione <code>set()</code>. (I pedanti che sanno come sono implementati gli insiemi vi faranno notare che questa non è esattamente l’invocazione di una funzione, ma la creazione di un’istanza di una classe. Vi <em>prometto</em> che imparerete la differenza più avanti in questo libro, ma per ora vi basti sapere che <code>set()</code> agisce come una funzione e restituisce un insieme.)
<li>Come ho menzionato in precedenza, un singolo insieme può contenere valori di qualsiasi tipo di dato. E, come ho menzionato in precedenza, gli insiemi <em>non sono ordinati</em>. Questo insieme non ricorda l’ordine originale della lista che è stata usata per crearlo. Se doveste aggiungere elementi a questo insieme, non ricorderebbe l’ordine in cui li avete aggiunti.
<li>La lista originale rimane invariata.
</ol>
<p id=emptyset>Non avete ancora alcun valore? Non è un problema. Potete creare un insieme vuoto.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_set = set()</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>a_set</kbd> <span class=u>②</span></a>
<samp class=pp>set()</samp>
<a><samp class=p>>>> </samp><kbd class=pp>type(a_set)</kbd> <span class=u>③</span></a>
<samp><class 'set'></samp>
<a><samp class=p>>>> </samp><kbd class=pp>len(a_set)</kbd> <span class=u>④</span></a>
<samp class=pp>0</samp>
<a><samp class=p>>>> </samp><kbd class=pp>not_sure = {}</kbd> <span class=u>⑤</span></a>
<samp class=p>>>> </samp><kbd class=pp>type(not_sure)</kbd>
<samp><class 'dict'></samp></pre>
<ol>
<li>Per creare un insieme vuoto, chiamate <code>set()</code> senza argomenti.
<li>La rappresentazione stampata di un insieme vuoto ha un’aria un po’ strana. Vi sareste aspettati <code>{}</code>, forse? Ma quella rappresentazione denoterebbe un dizionario vuoto. Imparerete cosa sono i dizionari più avanti in questo capitolo.
<li>Nonostante la strana rappresentazione stampata, questo <em>è</em> un insieme…
<li>…e questo insieme non ha elementi.
<li>A causa di alcuni cavilli storicamente legati a Python 2, non potete creare un insieme vuoto con due parentesi graffe. Questa notazione in realtà crea un dizionario vuoto, non un insieme vuoto.
</ol>
<h3 id=modifying-sets>Modificare un insieme</h3>
<p>Esistono due modi differenti per aggiungere valori a un insieme esistente: il metodo <code>add()</code> e il metodo <code>update()</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {1, 2}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.add(4)</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2, 4}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>len(a_set)</kbd> <span class=u>②</span></a>
<samp class=pp>3</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.add(1)</kbd> <span class=u>③</span></a>
<samp class=pp>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2, 4}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>len(a_set)</kbd> <span class=u>④</span></a>
<samp class=pp>3</samp></pre>
<ol>
<li>Il metodo <code>add()</code> prende un singolo argomento, che può essere di qualsiasi tipo di dato, e aggiunge il valore passato all’insieme.
<li>Ora questo insieme possiede 3 membri.
<li>Gli insiemi sono gruppi di <em>valori unici</em>. Se provate ad aggiungere un valore che è già contenuto nell’insieme, non succederà nulla. Non verrà sollevato un errore, è semplicemente un’operazione senza alcun effetto.
<li>Questo insieme possiede <em>ancora</em> 3 membri.
</ol>
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {1, 2, 3}</kbd>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2, 3}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.update({2, 4, 6})</kbd> <span class=u>①</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>a_set</kbd> <span class=u>②</span></a>
<samp class=pp>{1, 2, 3, 4, 6}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2, 3, 4, 5, 6, 8, 9, 13}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.update([10, 20, 30])</kbd> <span class=u>④</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}</samp></pre>
<ol>
<li>Il metodo <code>update()</code> prende come argomento un insieme e aggiunge tutti i suoi membri all’insieme originale. È come se aveste chiamato il metodo <code>add()</code> con ognuno dei membri dell’insieme.
<li>I valori duplicati vengono ignorati, dato che gli insiemi non possono contenere duplicati.
<li>In realtà, potete chiamare il metodo <code>update()</code> con un numero qualsiasi di argomenti. Quando viene invocato con due insiemi, il metodo <code>update()</code> aggiunge tutti i membri di ogni insieme all’insieme originale (scartando i duplicati).
<li>Il metodo <code>update()</code> può accettare oggetti di un certo numero di tipi di dato differenti, comprese le liste. Quando viene invocato con una lista, il metodo <code>update()</code> aggiunge tutti gli elementi della lista all’insieme originale.
</ol>
<h3 id=removing-from-sets>Rimuovere elementi da un insieme</h3>
<p>Esistono tre modi di rimuovere singoli elementi da un insieme. I primi due, <code>discard()</code> e <code>remove()</code>, hanno una sottile differenza.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}</kbd>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 3, 36, 6, 10, 45, 15, 21, 28}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.discard(10)</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 3, 36, 6, 45, 15, 21, 28}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.discard(10)</kbd> <span class=u>②</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 3, 36, 6, 45, 15, 21, 28}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.remove(21)</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{1, 3, 36, 6, 45, 15, 28}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.remove(21)</kbd> <span class=u>④</span></a>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 21</samp></pre>
<ol>
<li>Il metodo <code>discard()</code> prende un singolo valore come argomento e rimuove quel valore dall’insieme.
<li>Se invocate il metodo <code>discard()</code> con un valore che non è presente nell’insieme, non succederà nulla. Nessuna eccezione, è semplicemente un’operazione senza alcun effetto.
<li>Anche il metodo <code>remove()</code> prende un singolo valore come argomento e rimuove quel valore dall’insieme.
<li>Ecco la differenza: se il valore non è presente nell’insieme, il metodo <code>remove()</code> solleva un’eccezione di tipo <code>KeyError</code>.
</ol>
<p>Come le liste, gli insiemi sono dotati di un metodo <code>pop()</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.pop()</kbd> <span class=u>①</span></a>
<samp class=pp>1</samp>
<samp class=p>>>> </samp><kbd class=pp>a_set.pop()</kbd>
<samp class=pp>3</samp>
<samp class=p>>>> </samp><kbd class=pp>a_set.pop()</kbd>
<samp class=pp>36</samp>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>{6, 10, 45, 15, 21, 28}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.clear()</kbd> <span class=u>②</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set</kbd>
<samp class=pp>set()</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.pop()</kbd> <span class=u>③</span></a>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'</samp></pre>
<ol>
<li>Il metodo <code>pop()</code> rimuove un singolo valore da un insieme e restituisce quel valore. Tuttavia, dato che gli insiemi non sono ordinati, non c’è nessun “ultimo” valore in un insieme, quindi non c’è alcun modo di controllare quale sia il valore che viene rimosso. Il processo è completamente arbitrario.
<li>Il metodo <code>clear()</code> rimuove <em>tutti</em> i valori dall’insieme, lasciandovi con un insieme vuoto. Questo è equivalente a <code>a_set = set()</code>, che avrebbe creato un nuovo insieme vuoto e sovrascritto il precedente valore della variabile <var>a_set</var>.
<li>Il tentativo di invocare <code>pop()</code> per rimuovere un valore da un insieme vuoto solleverà un’eccezione di tipo <code>KeyError</code>.
</ol>
<h3 id=common-set-operations>Operazioni comuni sugli insiemi</h3>
<p>Il tipo <code>set</code> di Python supporta diverse operazioni comuni sugli insiemi.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>30 in a_set</kbd> <span class=u>①</span></a>
<samp class=pp>True</samp>
<samp class=p>>>> </samp><kbd class=pp>31 in a_set</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.union(b_set)</kbd> <span class=u>②</span></a>
<samp class=pp>{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.intersection(b_set)</kbd> <span class=u>③</span></a>
<samp class=pp>{9, 2, 12, 5, 21}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.difference(b_set)</kbd> <span class=u>④</span></a>
<samp class=pp>{195, 4, 76, 51, 30, 127}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.symmetric_difference(b_set)</kbd> <span class=u>⑤</span></a>
<samp class=pp>{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}</samp></pre>
<ol>
<li>Per verificare se un valore è un membro di un insieme, usate l’operatore <code>in</code>. Questo funziona come per le liste.
<li>Il metodo <code>union()</code> restituisce un nuovo insieme contenente tutti gli elementi che sono <em>in uno o nell’altro</em> insieme.
<li>Il metodo <code>intersection()</code> restituisce un nuovo insieme contenente tutti gli elementi che sono in <em>entrambi</em> gli insiemi.
<li>Il metodo <code>difference()</code> restituisce un nuovo insieme contenente tutti gli elementi che sono in <var>a_set</var> ma non in <var>b_set</var>.
<li>Il metodo <code>symmetric_difference()</code> restituisce un nuovo insieme contenente tutti gli elementi che sono in <em>esattamente uno</em> solo degli insiemi.
</ol>
<p>Tre di questi metodi sono simmetrici.
<pre class=screen>
# continua dall'esempio precedente
<a><samp class=p>>>> </samp><kbd class=pp>b_set.symmetric_difference(a_set)</kbd> <span class=u>①</span></a>
<samp class=pp>{3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set)</kbd> <span class=u>②</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>b_set.union(a_set) == a_set.union(b_set)</kbd> <span class=u>③</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>b_set.intersection(a_set) == a_set.intersection(b_set)</kbd> <span class=u>④</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>b_set.difference(a_set) == a_set.difference(b_set)</kbd> <span class=u>⑤</span></a>
<samp class=pp>False</samp></pre>
<ol>
<li>La differenza simmetrica tra <var>a_set</var> e <var>b_set</var> <em>sembra</em> diversa dalla differenza simmetrica tra <var>b_set</var> e <var>a_set</var>, ma ricordatevi che gli insiemi non sono ordinati. Due insiemi qualsiasi che contengono gli stessi valori (nessuno escluso) sono considerati uguali.
<li>E questo è esattamente quello che accade qui. Non fatevi ingannare dalla rappresentazione stampata di questi insiemi mostrata dalla Shell Python. Contengono gli stessi valori, quindi sono uguali.
<li>Anche l’unione tra due insiemi è simmetrica.
<li>Anche l’intersezione tra due insiemi è simmetrica.
<li>La differenza tra due insiemi non è simmetrica. Questo ha senso, perché l’operazione è analoga alla sottrazione di un numero da un altro. L’ordine degli operandi ha importanza.
</ol>
<p>Infine, ci sono alcune domande che potete porre agli insiemi.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_set = {1, 2, 3}</kbd>
<samp class=p>>>> </samp><kbd class=pp>b_set = {1, 2, 3, 4}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.issubset(b_set)</kbd> <span class=u>①</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>b_set.issuperset(a_set)</kbd> <span class=u>②</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_set.add(5)</kbd> <span class=u>③</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_set.issubset(b_set)</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>b_set.issuperset(a_set)</kbd>
<samp class=pp>False</samp></pre>
<ol>
<li><var>a_set</var> è un <dfn>sottoinsieme</dfn> di <var>b_set</var> — tutti i membri di <var>a_set</var> sono anche membri di <var>b_set</var>.
<li>Ponendo la stessa domanda al contrario, <var>b_set</var> è un <dfn>sovrainsieme</dfn> di <var>a_set</var>, perché tutti i membri di <var>a_set</var> sono anche membri di <var>b_set</var>.
<li>Appena aggiungete ad <var>a_set</var> un valore che non è presente in <var>b_set</var>, entrambi i metodi restituiscono <code>False</code>.
</ol>
<h3 id=sets-in-a-boolean-context>Insiemi in un contesto logico</h3>
<p>Potete usare gli insiemi in <a href=#booleans>un contesto logico</a> come quello di un’istruzione <code>if</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true(set())</kbd> <span class=u>①</span></a>
<samp>no, è falso</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true({'a'})</kbd> <span class=u>②</span></a>
<samp>sì, è vero</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true({False})</kbd> <span class=u>③</span></a>
<samp>sì, è vero</samp></pre>
<ol>
<li>In un contesto logico, un insieme vuoto è falso.
<li>Qualsiasi insieme con almeno un elemento è vero.
<li>Qualsiasi insieme con almeno un elemento è vero. Il valore degli elementi è irrilevante.
</ol>
<p class=a>⁂
<h2 id=dictionaries>Dizionari</h2>
<p>Un <dfn>dizionario</dfn> è un insieme non ordinato di coppie chiave-valore. Quando aggiungete una chiave a un dizionario, dovete anche aggiungere un valore per quella chiave. (Potete sempre cambiare il valore più tardi.) I dizionari Python sono ottimizzati per recuperare il valore quando conoscete la chiave, ma non viceversa.
<blockquote class='note compare perl5'>
<p><span class=u>☞</span>Un dizionario in Python è come un hash in Perl 5. In Perl 5, le variabili che memorizzano un hash cominciano sempre con il carattere <code>%</code>. In Python, le variabili possono essere chiamate in qualsiasi modo, e Python tiene traccia del tipo di dato internamente.
</blockquote>
<h3 id=creating-dictionaries>Creare un dizionario</h3>
<p>Creare un dizionario è facile. La sintassi è simile agli <a href=#sets>insiemi</a>, ma invece di valori avete coppie chiave-valore. Una volta che avete creato un dizionario, potete recuperarne i valori attraverso le loro chiavi.
<pre class=screen>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'}</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_dict</kbd>
<samp class=pp>{'server': 'db.diveintopython3.org', 'database': 'mysql'}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['server']</kbd> <span class=u>②</span></a>
'db.diveintopython3.org'
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['database']</kbd> <span class=u>③</span></a>
'mysql'
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['db.diveintopython3.org']</kbd> <span class=u>④</span></a>
<samp class=traceback>Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'db.diveintopython3.org'</samp></pre>
<ol>
<li>Per prima cosa, create un nuovo dizionario con due elementi e assegnatelo alla variabile <var>a_dict</var>. Ogni elemento è una coppia chiave-valore, e l’intero insieme di elementi è racchiuso tra parentesi graffe.
<li><code>'server'</code> è una chiave, e il suo valore associato, riferito da <code>a_dict['server']</code>, è <code>'db.diveintopython3.org'</code>.
<li><code>'database'</code> è una chiave, e il suo valore associato, riferito da <code>a_dict['database']</code>, è <code>'mysql'</code>.
<li>Potete ottenere i valori attraverso le chiavi, ma non potete ottenere le chiavi attraverso i valori. Quindi, <code>a_dict['server']</code> è <code>'db.diveintopython3.org'</code>, ma <code>a_dict['db.diveintopython3.org']</code> solleva un’eccezione perché <code>'db.diveintopython3.org'</code> non è una chiave.
</ol>
<h3 id=modifying-dictionaries>Modificare un dizionario</h3>
<p>I dizionari non hanno alcun limite predefinito sulla propria dimensione. Potete aggiungere nuove coppie chiave-valore a un dizionario in ogni momento, oppure potete modificare il valore di una chiave esistente. Continuando dall’esempio precedente:
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>a_dict</kbd>
<samp class=pp>{'server': 'db.diveintopython3.org', 'database': 'mysql'}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['database'] = 'blog'</kbd> <span class=u>①</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_dict</kbd>
<samp class=pp>{'server': 'db.diveintopython3.org', 'database': 'blog'}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['user'] = 'mark'</kbd> <span class=u>②</span></a>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict</kbd> <span class=u>③</span></a>
<samp class=pp>{'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['user'] = 'dora'</kbd> <span class=u>④</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_dict</kbd>
<samp class=pp>{'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}</samp>
<a><samp class=p>>>> </samp><kbd class=pp>a_dict['User'] = 'mark'</kbd> <span class=u>⑤</span></a>
<samp class=p>>>> </samp><kbd class=pp>a_dict</kbd>
<samp class=pp>{'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}</samp></pre>
<ol>
<li>Non potete avere chiavi duplicate in un dizionario. Assegnare un valore a una chiave esistente cancellerà il vecchio valore.
<li>Potete aggiungere nuove coppie chiave-valore in ogni momento. Questa sintassi è identica a quella per modificare valori già esistenti.
<li>Il nuovo elemento del dizionario (chiave <code>'user'</code>, valore <code>'mark'</code>) appare nel mezzo. In effetti, è stata solamente una coincidenza che gli elementi apparissero in ordine nel primo esempio; è allo stesso modo una coincidenza che appaiano fuori ordine ora.
<li>Assegnare un valore a una chiave esistente nel dizionario sostituisce semplicemente il vecchio valore con il nuovo.
<li>Questo assegnamento reinserirà <code>'mark'</code> come valore della chiave <code>'user'</code>? No! Guardate bene la chiave — c’è una <kbd>U</kbd> maiuscola in <kbd>'User'</kbd>. Le chiavi di un dizionario sono sensibili alle maiuscole, quindi questa istruzione crea una nuova coppia chiave-valore, senza sovrascriverne una esistente. A voi potrebbe sembrare simile, ma per quanto riguarda Python la chiave è completamente diversa.
</ol>
<h3 id=mixed-value-dictionaries>Dizionari a valori misti</h3>
<p>I dizionari non funzionano solo con le stringhe. I valori in un dizionario possono appartenere a qualsiasi tipo di dato, compresi interi, booleani, oggetti arbitrari e persino altri dizionari. E all’interno di un singolo dizionario i valori non devono essere tutti dello stesso tipo, ma potete mescolarli a piacimento. Le chiavi di un dizionario hanno maggiori restrizioni, ma possono essere stringhe, interi, e di pochi altri tipi. Potete mescolare anche i tipi di dato delle chiavi all’interno di un singolo dizionario.
<p>In effetti, avete già visto un dizionario con chiavi e valori che non sono stringhe nel <a href=il-vostro-primo-programma-python.html#divingin>vostro primo programma Python</a>.
<pre class='nd pp'><code>SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}</code></pre>
<p>Analizziamo questo oggetto nella shell interattiva.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],</kbd>
<samp class=p>... </samp><kbd class=pp> 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}</kbd>
<a><samp class=p>>>> </samp><kbd class=pp>len(SUFFIXES)</kbd> <span class=u>①</span></a>
<samp class=pp>2</samp>
<a><samp class=p>>>> </samp><kbd class=pp>1000 in SUFFIXES</kbd> <span class=u>②</span></a>
<samp class=pp>True</samp>
<a><samp class=p>>>> </samp><kbd class=pp>SUFFIXES[1000]</kbd> <span class=u>③</span></a>
<samp class=pp>['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>SUFFIXES[1024]</kbd> <span class=u>④</span></a>
<samp class=pp>['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']</samp>
<a><samp class=p>>>> </samp><kbd class=pp>SUFFIXES[1000][3]</kbd> <span class=u>⑤</span></a>
<samp class=pp>'TB'</samp></pre>
<ol>
<li>Similmente a quello che accade per le <a href=#lists>liste</a> e gli <a href=#sets>insiemi</a>, la funzione <code>len()</code> vi restituisce il numero di chiavi in un dizionario.
<li>E come per le liste e gli insiemi, potete usare l’operatore <code>in</code> per verificare se una chiave specifica è definita in un dizionario.
<li><code>1000</code> <em>è</em> una chiave nel dizionario <code>SUFFIXES</code> e il suo valore è una lista di otto elementi (otto stringhe, per essere precisi).
<li>Similmente, <code>1024</code> è una chiave nel dizionario <code>SUFFIXES</code> e il suo valore è anch’esso una lista di otto elementi.
<li>Dato che <code>SUFFIXES[1000]</code> è una lista, potete accedere ai singoli elementi contenuti in quella lista attraverso il loro indice a partire da 0.
</ol>
<h3 id=dictionaries-in-a-boolean-context>Dizionari in un contesto logico</h3>
<aside>I dizionari vuoti sono falsi; tutti gli altri dizionari sono veri.</aside>
<p>Potete usare i dizionari anche in <a href=#booleans>un contesto logico</a> come quello di un’istruzione <code>if</code>.
<pre class=screen>
<samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true({})</kbd> <span class=u>①</span></a>
<samp>no, è falso</samp>
<a><samp class=p>>>> </samp><kbd class=pp>is_it_true({'a': 1})</kbd> <span class=u>②</span></a>
<samp>sì, è vero</samp></pre>
<ol>
<li>In un contesto logico, un dizionario vuoto è falso.
<li>Qualsiasi dizionario con almeno una coppia chiave-valore è vero.
</ol>
<p class=a>⁂
<h2 id=none><code>None</code></h2>
<p><code><dfn>None</dfn></code> è una costante speciale in Python. È un valore <dfn>nullo</dfn>. <code>None</code> non è la stessa cosa di <code>False</code>. <code>None</code> non è 0. <code>None</code> non è una stringa vuota. Confrontare <code>None</code> con qualcos’altro che non sia <code>None</code> restituirà sempre <code>False</code>.
<p><code>None</code> è l’unico valore nullo. Ha un proprio tipo di dato (<code>NoneType</code>). Potete assegnare <code>None</code> a qualsiasi variabile, ma non potete creare altri oggetti di tipo <code>NoneType</code>. Tutte le varibili il cui valore è <code>None</code> sono uguali tra loro.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>type(None)</kbd>
<samp><class 'NoneType'></samp>
<samp class=p>>>> </samp><kbd class=pp>None == False</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>None == 0</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>None == ''</kbd>
<samp class=pp>False</samp>
<samp class=p>>>> </samp><kbd class=pp>None == None</kbd>
<samp class=pp>True</samp>
<samp class=p>>>> </samp><kbd class=pp>x = None</kbd>
<samp class=p>>>> </samp><kbd class=pp>x == None</kbd>
<samp class=pp>True</samp>
<samp class=p>>>> </samp><kbd class=pp>y = None</kbd>
<samp class=p>>>> </samp><kbd class=pp>x == y</kbd>
<samp class=pp>True</samp>
</pre>
<h3 id=none-in-a-boolean-context><code>None</code> in un contesto logico</h3>
<p>In <a href=#booleans>un contesto logico</a>, <code>None</code> è falso e <code>not None</code> è vero.
<pre class='nd screen'>
<samp class=p>>>> </samp><kbd class=pp>def is_it_true(anything):</kbd>
<samp class=p>... </samp><kbd class=pp> if anything:</kbd>
<samp class=p>... </samp><kbd class=pp> print('sì, è vero')</kbd>
<samp class=p>... </samp><kbd class=pp> else:</kbd>
<samp class=p>... </samp><kbd class=pp> print('no, è falso')</kbd>
<samp class=p>...</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(None)</kbd>
<samp>no, è falso</samp>
<samp class=p>>>> </samp><kbd class=pp>is_it_true(not None)</kbd>
<samp>sì, è vero</samp></pre>
<p class=a>⁂
<h2 id=furtherreading>Letture di approfondimento</h2>
<ul>
<li><a href=http://docs.python.org/3.1/library/stdtypes.html#boolean-operations-and-or-not>Operazioni logiche</a>
<li><a href=http://docs.python.org/3.1/library/stdtypes.html#numeric-types-int-float-long-complex>Tipi numerici</a>
<li><a href=http://docs.python.org/3.1/library/stdtypes.html#sequence-types-str-unicode-list-tuple-buffer-xrange>Tipi di sequenza</a>
<li><a href=http://docs.python.org/3.1/library/stdtypes.html#set-types-set-frozenset>Tipi di insieme</a>
<li><a href=http://docs.python.org/3.1/library/stdtypes.html#mapping-types-dict>Tipi di correlazione</a>
<li><a href=http://docs.python.org/3.1/library/fractions.html>Il modulo <code>fractions</code></a>
<li><a href=http://docs.python.org/3.1/library/math.html>Il modulo <code>math</code></a>
<li><a href=http://www.python.org/dev/peps/pep-0237/><abbr>PEP</abbr> 237: Unificare gli interi e gli interi lunghi</a>
<li><a href=http://www.python.org/dev/peps/pep-0238/><abbr>PEP</abbr> 238: Modificare l’operatore di divisione</a>
</ul>
<p class=v><a href=il-vostro-primo-programma-python.html rel=prev title='indietro a “Il vostro primo programma Python”'><span class=u>☜</span></a> <a href=descrizioni.html rel=next title='avanti a “Descrizioni”'><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>