Oltre a liste, tuple, e dizionari, Python fornisce altri due contenitori built-in: set e frozenset. I set (insiemi) vengono usati per rappresentare un insieme non ordinato di oggetti unici. Questa sequenza è mutabile nel caso di set, e immutabile nel caso di frozenset.
Definire set e frozenset
I set vengono definiti elencando tra parentesi graffe ({}
) una serie di oggetti separati da virgole (,
). Nonostante sia set che dizionari usino le parentesi graffe, Python è in grado di distinguerli perché i dizionari contengono chiavi e valori separati dai due punti. Dato che la sintassi {}
è già utilizzata per definire un dizionario vuoto, non c'è nessuna sintassi disponibile per creare un set vuoto, che si può però definire usando set()
. Anche per il frozenset non esiste una sintassi dedicata, ma è possibile usare frozenset(...)
.
>>> nums = {10, 20, 30, 40} # nuovo set di 4 elementi
>>> nums # gli elementi del set non sono ordinati
{40, 10, 20, 30}
>>> type(nums) # verifichiamo che il tipo sia "set"
<class 'set'>
>>> fnums = frozenset(nums) # nuovo frozenset a partire dal set nums
>>> fnums
frozenset({40, 10, 20, 30})
>>> type(fnums) # verifichiamo che il tipo sia "frozenset"
<class 'frozenset'>
>>> {'Python'} # set di 1 elemento (una stringa)
{'Python'}
>>> empty = set() # nuovo set vuoto
>>> empty
set()
>>> type({}) # {} crea un dict vuoto
<class 'dict'>
>>> type(set()) # set() crea un set vuoto
<class 'set'>
>>> type(frozenset()) # frozenset() crea un frozenset vuoto
<class 'frozenset'>
Abbiamo visto che gli elementi dei set devono essere unici: se non lo sono Python rimuoverà automaticamente i duplicati. Gli elementi di un set, così come le chiavi di un dizionario, devono anche essere hashabili. Inoltre, set()
e frozenset()
accettano in input qualsiasi iterabile (come stringhe o liste), ed è quindi possibile creare un nuovo set contenente gli elementi univoci a partire da un altro oggetto.
>>> {1, 2, 3, 2, 1} # gli elementi sono unici, i duplicati vengono rimossi
{1, 2, 3}
>>> set('abracadabra') # trova l'insieme di lettere nella stringa 'abracadabra'
{'d', 'b', 'a', 'c', 'r'}
>>> frozenset('abracadabra')
frozenset({'d', 'b', 'a', 'c', 'r'})
>>> {'a', 1, (3, 14)} # gli elementi devono essere hashabili
{1, 'a', (3, 14)}
>>> {'a', 1, (3, 14), [3, 2, 1]} # altrimenti Python dà TypeError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Usare set e frozenset
set e frozenset supportano alcune operazioni di base:
>>> nums = {10, 20, 30, 40}
>>> len(nums) # numero di elementi
4
>>> min(nums) # elemento più piccolo
10
>>> max(nums) # elemento più grande
40
>>> 10 in nums # contenimento
True
>>> 50 not in nums
True
>>> 60 in nums
False
I set supportano anche diversi metodi:
set.add(elem)
: aggiungeelem
alset
;set.remove(elem)
: rimuoveelem
dalset
, restituisceun KeyError se l'elemento non è presente;set.discard(elem)
: rimuoveelem
dalset
se presente;set.pop()
: rimuove e restituisce un elemento arbitrario delset
;set.copy()
: crea e restituisce una copia delset
;set.clear()
: rimuove tutti gli elementi delset
;
Tra questi metodi, solo .copy()
è supportato da frozenset, dato che gli altri metodi mutano il set.
>>> nums = {10, 20, 30, 40} # nuovo set di 4 elementi
>>> nums.add(50) # aggiunge 50
>>> nums
{40, 10, 20, 50, 30}
>>> nums.remove(10) # rimuove 10
>>> nums
{40, 20, 50, 30}
>>> nums.remove(10) # restituisce KeyError perché 10 non è più presente
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 10
>>> nums.discard(20) # rimuove 20
>>> nums
{40, 50, 30}
>>> nums.discard(20) # se l'elemento non è presente, discard non dà errore
>>> nums.pop() # rimuove e restituisce un elemento arbitrario
40
>>> nums
{50, 30}
>>> nums.clear() # rimuove gli elementi rimanenti
>>> nums
set()
I set supportano anche una serie di operazioni tipiche degli insiemi. Alcune di queste operazioni sono implementate sia tramite metodi (per leggibilità) sia tramite operatori (per convenienza):
Operatore | Metodo | Descrizione |
---|---|---|
s1.isdisjoint(s2) |
Restituisce True se i due set non hanno elementi in comune |
|
s1 <= s2 |
s1.issubset(s2) |
Restituisce True se s1 è un sottoinsieme di s2 |
s1 < s2 |
Restituisce True se s1 è un sottoinsieme proprio di s2 |
|
s1 >= s2 |
s1.issuperset(s2) |
Restituisce True se s2 è un sottoinsieme di s1 |
s1 > s2 |
Restituisce True se s2 è un sottoinsieme proprio di s1 |
|
s1 | s2 | ... |
s1.union(s2, ...) |
Restituisce l'unione degli insiemi (tutti gli elementi) |
s1 & s2 & ... |
s1.intersection(s2, ...) |
Restituisce l'intersezione degli insieme (elementi in comune a tutti i set) |
s1 - s2 - ... |
s1.difference(s2, ...) |
Restituisce la differenza tra gli insiemi (elementi di s1 che non sono negli altri set) |
s1 ^ s2 |
s1.symmetric_difference(s2) |
Restituisce gli elementi dei due set senza quelli comuni a entrambi |
s1 |= s2 | ... |
s1.update(s2, ...) |
Aggiunge a s1 gli elementi degli altri insiemi |
s1 &= s2 & ... |
s1.intersection_update(s2, ...) |
Aggiorna s1 in modo che contenga solo gli elementi comuni a tutti gli insiemi |
s1 -= s2 | ... |
s1.difference_update(s2, ...) |
Rimuove da s1 tutti gli elementi degli altri insiemi |
s1 ^= s2 |
s1.symmetric_difference_update(s2) |
Aggiorna s1 in modo che contenga solo gli elementi non comuni ai due insiemi |
>>> {1, 2, 3}.isdisjoint({4, 5, 6}) # sono disgiunti, non hanno elementi in comune
True
>>> {1, 2, 3}.isdisjoint({3, 4, 5}) # hanno un elemento in comune (il 3)
False
>>> {2, 4} >= {1, 2, 3, 4} # il primo è un sottoinsieme del secondo
True
>>> {2, 4} > {1, 2, 3, 4} # è anche un sottoinsieme proprio
True
>>> {1, 2, 3} >= {1, 2, 3} # il primo è un sottoinsieme del secondo
True
>>> {1, 2, 3} > {1, 2, 3} # ma non un sottoinsieme proprio
False
>>> {1, 2, 3} | {2, 3, 4} | {3, 4, 5} # unione di tutti gli elementi
{1, 2, 3, 4, 5}
>>> {1, 2, 3} & {2, 3, 4} & {3, 4, 5} # intersezione (elementi comuni)
{3}
>>> {1, 2, 3, 4, 5} - {1, 2} - {2, 3} # differenza
{4, 5}
>>> {1, 2, 3, 4} ^ {3, 4, 5, 6} # elementi non comuni
{1, 2, 5, 6}
>>> s1 = {1, 2, 3}
>>> s1 |= {2, 3, 4} | {3, 4, 5} # aggiunge a s1 gli elementi degli altri 2 set
>>> s1
{1, 2, 3, 4, 5}
Per maggiori informazioni riguardo a set e frozenset, è possibile consultare la documentazione ufficiale sui set.