In Python, una collezione è un oggetto che contiene un gruppo di elementi e permette di manipolarli come un’unità unica.
Le collezioni in genere supportano:
- iterazione (
for elemento in collezione) - verifica di appartenenza (
x in collezione) - determinazione della lunghezza (
len(collezione)) - accesso tramite indice o chiave (se ordinata o associativa)
Python non ha un’«interfaccia collezione» rigorosa, ma segue protocolli informali. Se un oggetto implementa
__iter__,__len__,__contains__, può essere considerato una collezione.
- Cosa NON è una collezione
- Collezioni integrate
- Collezioni estese dalla libreria standard
- Altri tipi simili alle collezioni
- 1. Liste —
list - 2. Dizionari —
dict - 3. Tuple —
tuple - 4. SimpleNamespace
- 5. Insiemi —
set - 6. Insiemi immutabili —
frozenset - 7. namedtuple — tuple nominate
- 8. deque — coda a doppia estremità
- 9. Counter — contatore di elementi
- 10. defaultdict — dizionario con valori predefiniti
- 11. dataclass — classi dati
- 12. UserList — liste personalizzate
- 13. UserDict — dizionari personalizzati
- 📈 Confronto memoria e prestazioni
- 1. Memoria:
listvstuplevsarray.array - 2. Velocità di accesso:
listvstuplevsarray.array - 3. Memoria:
dictvsSimpleNamespacevsdataclass - 4. Ottimizzazione memoria:
dataclasscon__slots__ - 5. Velocità di ricerca:
listvsset - 6. Memoria:
setvsfrozenset - 7. Velocità di aggiunta:
list.appendvsdeque.appendvsdeque.appendleft
- 1. Memoria:
- 🧠 Raccomandazioni prestazioni
- 📊 Confronto collezioni
- 💡 Quando usare cosa?
Cosa NON è una collezione
I seguenti tipi non sono collezioni, poiché non contengono gruppi di elementi:
int,float,bool— valori scalariNone— assenza di valore- funzioni, moduli, classi — sono oggetti, ma non contenitori di dati (a meno che non contengano
__dict__)
Collezioni integrate
Disponibili senza import:
| Tipo | Descrizione |
|---|---|
list | Sequenza ordinata, modificabile. |
tuple | Sequenza ordinata, immutabile. |
dict | Mappatura chiave-valore ordinata (da Python 3.7). |
set | Collezione non ordinata di elementi unici. |
frozenset | Versione immutabile di set. |
Collezioni estese dalla libreria standard
| Tipo | Modulo | Scopo |
|---|---|---|
SimpleNamespace | types | Oggetto con attributi dinamici (alternativa al dict con accesso tramite .). |
namedtuple | collections | Tupla immutabile con campi nominati. |
deque | collections | Coda a doppia estremità — efficiente per aggiunte/rimozioni a entrambe le estremità. |
Counter | collections | Sottoclasse di dict per contare oggetti hashabili. |
defaultdict | collections | Dizionario con valori predefiniti per chiavi mancanti. |
dataclass | dataclasses | Genera automaticamente __init__, __repr__, __eq__, ecc. |
UserList | collections | Classe base per oggetti tipo lista personalizzati. |
UserDict | collections | Classe base per oggetti tipo dizionario personalizzati. |
Altri tipi simili alle collezioni
Anche se non sempre chiamati “collezioni”, questi tipi rappresentano o memorizzano gruppi di dati.
1. str — stringa
Sequenza ordinata, immutabile di caratteri.
s = "Python"
print(len(s)) # → 6
print(s[0]) # → P
print('y' in s) # → True
print(list(s)) # → ['P', 'y', 't', 'h', 'o', 'n']
2. bytes, bytearray
bytes— sequenza immutabile di byte.bytearray— versione modificabile.
b = b"ciao"
print(b[0]) # → 99
print(len(b)) # → 4
ba = bytearray(b"ciao")
ba[0] = 72
print(ba) # → bytearray(b'Hiao')
3. range
Sequenza numerica lazy, ordinata. Non memorizza gli elementi in memoria.
r = range(3)
print(list(r)) # → [0, 1, 2]
print(1 in r) # → True
print(r[2]) # → 2
4. array.array
Memorizza dati numerici omogenei in modo compatto (come in C).
from array import array
arr = array('i', [1, 2, 3]) # 'i' = intero con segno
print(arr) # → array('i', [1, 2, 3])
5. Generatori e iteratori
Non memorizzano dati — li generano su richiesta. Non supportano len() né indicizzazione.
gen = (x * 2 for x in range(3))
print(list(gen)) # → [0, 2, 4]
# len(gen) → TypeError
6. ChainMap (da collections)
Raggruppa più dizionari in un’unica vista — la ricerca attraversa le mappe in ordine.
from collections import ChainMap
d1 = {'a': 1}
d2 = {'b': 2}
cm = ChainMap(d1, d2)
print(cm['a']) # → 1
print(cm['b']) # → 2
7. OrderedDict (da collections)
Dizionario che mantiene l’ordine di inserimento. Rilevante per Python < 3.7.
from collections import OrderedDict
od = OrderedDict([('a', 1), ('b', 2)])
print(od) # → OrderedDict([('a', 1), ('b', 2)])
8. enum.Enum, enum.Flag
Collezioni di costanti nominate.
from enum import Enum
class Colore(Enum):
ROSSO = 1
VERDE = 2
print(list(Colore)) # → [<Colore.ROSSO: 1>, <Colore.VERDE: 2>]
9. typing.NamedTuple, typing.TypedDict
Wrapper tipizzati su namedtuple e dict.
from typing import NamedTuple, TypedDict
class Persona(NamedTuple):
nome: str
età: int
p = Persona("Giulia", 25)
class Film(TypedDict):
titolo: str
anno: int
m: Film = {"titolo": "Matrix", "anno": 1999}
10. heapq, bisect — strumenti, non collezioni
Lavorano con collezioni, ma non lo sono:
heapq— algoritmo coda di priorità tramite liste.bisect— mantiene ordine in liste ordinate.
1. Liste — list
Collezione ordinata, modificabile. Gli elementi possono ripetersi, tutti i tipi sono ammessi.
Usata quando serve una sequenza flessibile: aggiungere, rimuovere, modificare elementi.
Creazione: []
marco_list = ["Marco", "Roma", 30, "ingegnere"]
print(f"Creazione lista: {marco_list}")
# → Creazione lista: ['Marco', 'Roma', 30, 'ingegnere']
print(f"Elemento all’indice 0: {marco_list[0]}")
# → Elemento all’indice 0: Marco
marco_list[2] = 31
print(f"Dopo modifica: {marco_list}")
# → Dopo modifica: ['Marco', 'Roma', 31, 'ingegnere']
marco_list.append("sposato")
print(f"Dopo append: {marco_list}")
# → Dopo append: ['Marco', 'Roma', 31, 'ingegnere', 'sposato']
marco_list.insert(1, "Italia")
print(f"Dopo insert: {marco_list}")
# → Dopo insert: ['Marco', 'Italia', 'Roma', 31, 'ingegnere', 'sposato']
marco_list.remove("ingegnere")
print(f"Dopo remove per valore: {marco_list}")
# → Dopo remove per valore: ['Marco', 'Italia', 'Roma', 31, 'sposato']
del marco_list[2]
print(f"Dopo cancellazione per indice: {marco_list}")
# → Dopo cancellazione per indice: ['Marco', 'Italia', 31, 'sposato']
marco_list.extend(["hobby", "pesca"])
print(f"Dopo extend: {marco_list}")
# → Dopo extend: ['Marco', 'Italia', 31, 'sposato', 'hobby', 'pesca']
marco_list.pop()
print(f"Dopo pop: {marco_list}")
# → Dopo pop: ['Marco', 'Italia', 31, 'sposato', 'hobby']
2. Dizionari — dict
Collezione di coppie chiave → valore. Le chiavi devono essere hashabili. Da Python 3.7, l’ordine di inserimento è preservato.
Utile per dati strutturati: profili, configurazioni, JSON.
Creazione: {}
giulia_dict = {"nome": "Giulia", "età": 25, "città": "Firenze", "professione": "artista"}
print(f"Creazione dict: {giulia_dict}")
# → Creazione dict: {'nome': 'Giulia', 'età': 25, 'città': 'Firenze', 'professione': 'artista'}
print(f"Valore per chiave 'nome': {giulia_dict['nome']}")
# → Valore per chiave 'nome': Giulia
giulia_dict["età"] = 26
print(f"Dopo aggiornamento: {giulia_dict}")
# → Dopo aggiornamento: {'nome': 'Giulia', 'età': 26, 'città': 'Firenze', 'professione': 'artista'}
giulia_dict["hobby"] = "pittura"
print(f"Dopo aggiunta coppia: {giulia_dict}")
# → Dopo aggiunta coppia: {'nome': 'Giulia', 'età': 26, 'città': 'Firenze', 'professione': 'artista', 'hobby': 'pittura'}
del giulia_dict["città"]
print(f"Dopo cancellazione coppia: {giulia_dict}")
# → Dopo cancellazione coppia: {'nome': 'Giulia', 'età': 26, 'professione': 'artista', 'hobby': 'pittura'}
hobby = giulia_dict.pop("hobby")
print(f"Dopo pop: {giulia_dict}, valore: {hobby}")
# → Dopo pop: {'nome': 'Giulia', 'età': 26, 'professione': 'artista'}, valore: pittura
print(f"Chiave 'nome' esiste: {'nome' in giulia_dict}")
# → Chiave 'nome' esiste: True
3. Tuple — tuple
Collezione ordinata, immutabile. Adatta a dati fissi.
Usata quando l’immutabilità è importante: coordinate, parametri, valori di ritorno.
Creazione: ()
marco_tuple = ("Marco", "Roma", 30, "ingegnere")
print(f"Creazione tupla: {marco_tuple}")
# → Creazione tupla: ('Marco', 'Roma', 30, 'ingegnere')
print(f"Elemento all’indice 2: {marco_tuple[2]}")
# → Elemento all’indice 2: 30
# marco_tuple[0] = "Luca" → TypeError
# marco_tuple.append("qualcosa") → AttributeError
- Le tuple consumano meno memoria e sono più veloci delle liste.
- Ideali quando la modificabilità non serve.
4. SimpleNamespace
Classe semplice da types per creare oggetti con attributi dinamici. Accesso tramite notazione a punto (obj.attr).
Utile quando si vuole la sintassi obj.nome senza definire una classe completa.
from types import SimpleNamespace
giulia_ns = SimpleNamespace(nome="Giulia", età=25, città="Firenze")
print(f"Oggetto: {giulia_ns}")
# → Oggetto: namespace(nome='Giulia', età=25, città='Firenze')
print(f"Nome: {giulia_ns.nome}")
# → Nome: Giulia
giulia_ns.età = 26
print(f"Dopo aggiornamento: {giulia_ns}")
# → Dopo aggiornamento: namespace(nome='Giulia', età=26, città='Firenze')
giulia_ns.professione = "artista"
print(f"Con nuovo attributo: {giulia_ns}")
# → Con nuovo attributo: namespace(nome='Giulia', età=26, città='Firenze', professione='artista')
del giulia_ns.città
print(f"Dopo cancellazione: {giulia_ns}")
# → Dopo cancellazione: namespace(nome='Giulia', età=26, professione='artista')
setattr(giulia_ns, "hobby", "pittura")
print(f"Tramite setattr: {giulia_ns}")
# → Tramite setattr: namespace(nome='Giulia', età=26, professione='artista', hobby='pittura')
delattr(giulia_ns, "hobby")
print(f"Tramite delattr: {giulia_ns}")
# → Tramite delattr: namespace(nome='Giulia', età=26, professione='artista')
- Alternativa al dict quando
obj.nomeè preferibile aobj['nome'].
5. Insiemi — set
Collezione non ordinata di elementi unici. Supporta operazioni insiemistiche: unione, intersezione, differenza.
Usata per rimuovere duplicati e verificare appartenenza.
Creazione: {} o set()
numeri = {1, 2, 3, 3, 2, 1}
print(f"Insieme: {numeri}")
# → Insieme: {1, 2, 3}
numeri.add(4)
print(f"Dopo aggiunta: {numeri}")
# → Dopo aggiunta: {1, 2, 3, 4}
numeri.remove(2)
print(f"Dopo rimozione: {numeri}")
# → Dopo rimozione: {1, 3, 4}
altro = {3, 4, 5}
print(f"Unione: {numeri | altro}")
# → Unione: {1, 3, 4, 5}
print(f"Intersezione: {numeri & altro}")
# → Intersezione: {3, 4}
print(f"Differenza: {numeri - altro}")
# → Differenza: {1}
6. Insiemi immutabili — frozenset
Versione immutabile di set. Può essere usata come chiave di dict o elemento di un altro insieme.
frozen = frozenset([1, 2, 3, 2])
print(f"frozenset: {frozen}")
# → frozenset: frozenset({1, 2, 3})
altro = frozenset([3, 4])
print(f"Intersezione: {frozen & altro}")
# → Intersezione: frozenset({3})
print(f"Unione: {frozen | altro}")
# → Unione: frozenset({1, 2, 3, 4})
# frozen.add(5) → AttributeError
7. namedtuple — tuple nominate
Struttura immutabile con accesso per nome di campo. Più leggibile delle tuple classiche.
from collections import namedtuple
Persona = namedtuple("Persona", ["nome", "età", "città"])
giulia = Persona("Giulia", 25, "Firenze")
print(f"Oggetto: {giulia}")
# → Oggetto: Persona(nome='Giulia', età=25, città='Firenze')
print(f"Nome: {giulia.nome}")
# → Nome: Giulia
print(f"Età: {giulia[1]}")
# → Età: 25
# giulia.età = 26 → AttributeError
giulia_nuova = giulia._replace(età=26)
print(f"Copia modificata: {giulia_nuova}")
# → Copia modificata: Persona(nome='Giulia', età=26, città='Firenze')
- Ideale per record: punti, utenti, configurazioni — quando contano immutabilità e leggibilità.
8. deque — coda a doppia estremità
Ottimizzata per aggiunte/rimozioni veloci a entrambe le estremità. Più efficiente di list per appendleft, popleft.
from collections import deque
d = deque([1, 2, 3])
print(f"deque iniziale: {d}")
# → deque iniziale: deque([1, 2, 3])
d.appendleft(0)
print(f"Dopo appendleft: {d}")
# → Dopo appendleft: deque([0, 1, 2, 3])
d.append(4)
print(f"Dopo append: {d}")
# → Dopo append: deque([0, 1, 2, 3, 4])
sinistra = d.popleft()
print(f"Dopo popleft: {sinistra}, rimanente: {d}")
# → Dopo popleft: 0, rimanente: deque([1, 2, 3, 4])
destra = d.pop()
print(f"Dopo pop: {destra}, rimanente: {d}")
# → Dopo pop: 4, rimanente: deque([1, 2, 3])
- Usata in algoritmi: BFS, cache LRU, buffer — quando le operazioni alle estremità devono essere veloci.
9. Counter — contatore di elementi
Conta la frequenza degli elementi in un iterabile. Utile per statistiche e analisi.
from collections import Counter
testo = "abracadabra"
c = Counter(testo)
print(f"Conteggio lettere: {c}")
# → Conteggio lettere: Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
print(f"Frequenza di 'a': {c['a']}")
# → Frequenza di 'a': 5
print(f"Top 3: {c.most_common(3)}")
# → Top 3: [('a', 5), ('b', 2), ('r', 2)]
c2 = Counter("bukva")
c.update(c2)
print(f"Dopo update: {c}")
# → Dopo update: Counter({'a': 6, 'b': 3, 'r': 2, 'c': 1, 'd': 1, 'u': 1, 'k': 1, 'v': 1})
- Utile per analisi testi, log, votazioni — ovunque serva contare «cosa appare più spesso».
10. defaultdict — dizionario con valori predefiniti
Crea automaticamente valori predefiniti per chiavi mancanti. Elimina verifiche if key in dict.
from collections import defaultdict
dd_list = defaultdict(list)
dd_list["frutti"].append("mela")
dd_list["frutti"].append("banana")
print(f"Lista: {dict(dd_list)}")
# → Lista: {'frutti': ['mela', 'banana']}
dd_int = defaultdict(int)
for char in "abracadabra":
dd_int[char] += 1
print(f"Conteggi: {dict(dd_int)}")
# → Conteggi: {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
dd_set = defaultdict(set)
dd_set["città"].add("Roma")
dd_set["città"].add("Firenze")
print(f"Insieme: {dict(dd_set)}")
# → Insieme: {'città': {'Roma', 'Firenze'}}
- Elimina codice ripetitivo come
if key not in d: d[key] = []. - Rende il codice più pulito e sicuro.
11. dataclass — classi dati
Decoratore che genera automaticamente __init__, __repr__, __eq__, ecc.
from dataclasses import dataclass
@dataclass
class Persona:
nome: str
età: int
città: str = "Non specificata"
giulia = Persona("Giulia", 25)
print(f"Oggetto: {giulia}")
# → Oggetto: Persona(nome='Giulia', età=25, città='Non specificata')
print(f"Nome: {giulia.nome}")
# → Nome: Giulia
giulia.età = 26
print(f"Dopo aggiornamento: {giulia}")
# → Dopo aggiornamento: Persona(nome='Giulia', età=26, città='Non specificata')
bob = Persona("Bob", 30)
print(f"Giulia == Bob: {giulia == bob}")
# → Giulia == Bob: False
@dataclass(frozen=True)
class PersonaImmutabile:
nome: str
età: int
ivan = PersonaImmutabile("Ivan", 40)
# ivan.età = 41 → FrozenInstanceError
- Sostituisce la scrittura manuale di
__init__,__repr__,__eq__. - Ideale per DTO, configurazioni, modelli.
12. UserList — liste personalizzate
Eredita da collections.UserList. Usata per creare liste con comportamento personalizzato.
from collections import UserList
class ListaConLog(UserList):
def append(self, item):
print(f"[LOG] Aggiunta: {item}")
super().append(item)
def remove(self, item):
print(f"[LOG] Rimozione: {item}")
super().remove(item)
log_list = ListaConLog([1, 2, 3])
print(f"Iniziale: {log_list}")
# → Iniziale: [1, 2, 3]
log_list.append(4)
# → [LOG] Aggiunta: 4
print(f"Dopo append: {log_list}")
# → Dopo append: [1, 2, 3, 4]
log_list.remove(2)
# → [LOG] Rimozione: 2
print(f"Dopo remove: {log_list}")
# → Dopo remove: [1, 3, 4]
- Utile per aggiungere log, validazioni, o modificare il comportamento standard delle liste.
13. UserDict — dizionari personalizzati
Eredita da collections.UserDict. Usata per creare dizionari con comportamento personalizzato.
from collections import UserDict
class DictChiaviMinuscole(UserDict):
def __setitem__(self, key, value):
key = key.lower() if isinstance(key, str) else key
super().__setitem__(key, value)
def __getitem__(self, key):
key = key.lower() if isinstance(key, str) else key
return super().__getitem__(key)
ld = DictChiaviMinuscole()
ld["Nome"] = "Giulia"
print(f"Valore per 'Nome': {ld['Nome']}")
# → Valore per 'Nome': Giulia
print(f"Valore per 'nome': {ld['nome']}")
# → Valore per 'nome': Giulia
print(f"Chiavi: {list(ld.keys())}")
# → Chiavi: ['nome']
- Usata per normalizzare chiavi, validare, loggare, fare caching, ecc.
📈 Confronto memoria e prestazioni
La scelta della collezione influenza prestazioni e consumo di memoria. Di seguito benchmark pratici.
1. Memoria: list vs tuple vs array.array
import sys
from array import array
n = 1_000_000
data = list(range(n))
data_t = tuple(range(n))
data_a = array('i', range(n))
print(f"list: {sys.getsizeof(data) / 1024 / 1024:.2f} MB")
# → list: 8.00 MB
print(f"tuple: {sys.getsizeof(data_t) / 1024 / 1024:.2f} MB")
# → tuple: 8.00 MB
print(f"array: {sys.getsizeof(data_a) / 1024 / 1024:.2f} MB")
# → array: 3.81 MB
array.arrayusa ~2x meno memoria per numeri.listetupleconsumano memoria simile, matupleè leggermente più veloce in iterazione.
2. Velocità di accesso: list vs tuple vs array.array
import time
def time_access(collection, name):
start = time.perf_counter()
total = 0
for i in range(len(collection)):
total += collection[i]
end = time.perf_counter()
print(f"{name}: {end - start:.4f} secondi")
n = 10_000_000
lst = list(range(n))
tpl = tuple(range(n))
arr = array('i', range(n))
time_access(lst, "list") # → list: 1.2000 secondi
time_access(tpl, "tuple") # → tuple: 1.0000 secondi
time_access(arr, "array") # → array: 0.8000 secondi
array.arrayè il più veloce per dati numerici.tupleè 10–20% più veloce dilist.- La differenza è evidente su larga scala.
3. Memoria: dict vs SimpleNamespace vs dataclass
d = {"nome": "A", "età": 25, "città": "X", "hobby": "Y", "lavoro": "Z"}
ns = SimpleNamespace(nome="A", età=25, città="X", hobby="Y", lavoro="Z")
dc = PersonaDC("A", 25, "X", "Y", "Z")
print(f"dict: {sys.getsizeof(d)} byte") # → 232
print(f"SimpleNamespace: {sys.getsizeof(ns)} byte") # → 64
print(f"dataclass: {sys.getsizeof(dc)} byte") # → 64
print(f"ns.__dict__: {sys.getsizeof(ns.__dict__)} byte") # → 232
SimpleNamespaceedataclassconsumano tanta memoria quantodicta causa di__dict__.- Usa
__slots__per risparmiare memoria.
4. Ottimizzazione memoria: dataclass con __slots__
@dataclass
class PersonaSlots:
__slots__ = ("nome", "età", "città", "hobby", "lavoro")
nome: str
età: int
città: str
hobby: str
lavoro: str
dc_slots = PersonaSlots("A", 25, "X", "Y", "Z")
print(f"dataclass + slots: {sys.getsizeof(dc_slots)} byte")
# → 80 byte
# dc_slots.nuovo = "valore" → AttributeError
__slots__risparmia memoria e accelera l’accesso agli attributi.- Contropartita: non si possono aggiungere attributi dinamici.
5. Velocità di ricerca: list vs set
n = 1_000_000
lst = list(range(n))
st = set(range(n))
def time_in(collection, target, name):
start = time.perf_counter()
for _ in range(1000):
_ = target in collection
end = time.perf_counter()
print(f"{name} (ricerca {target}): {end - start:.4f} secondi")
time_in(lst, 999_999, "list") # → 10.0000 secondi
time_in(st, 999_999, "set") # → 0.0005 secondi
setè migliaia di volte più veloce dilistper verifiche di appartenenza.- Usa sempre
setper verifiche frequenti dix in collection.
6. Memoria: set vs frozenset
s = set(range(1000))
fs = frozenset(range(1000))
print(f"set: {sys.getsizeof(s)} byte") # → 32792
print(f"frozenset: {sys.getsizeof(fs)} byte") # → 32792
frozensetesetconsumano memoria identica.- La differenza è solo l’immutabilità.
7. Velocità di aggiunta: list.append vs deque.append vs deque.appendleft
from collections import deque
import time
def time_append(collection, n, method='append'):
start = time.perf_counter()
for i in range(n):
if method == 'appendleft' and hasattr(collection, 'appendleft'):
collection.appendleft(i)
else:
collection.append(i)
end = time.perf_counter()
return end - start
n = 100_000
lst = []
dq = deque()
time_list_append = time_append(lst, n) # → 0.0100 secondi
time_deque_append = time_append(dq, n) # → 0.0100 secondi
time_deque_appendleft = time_append(deque(), n, 'appendleft') # → 0.0100 secondi
# list.insert(0):
lst = []
start = time.perf_counter()
for i in range(n):
lst.insert(0, i)
end = time.perf_counter()
print(f"list.insert(0): {end - start:.4f} secondi") # → 5.0000 secondi
deque.appendleftè O(1), a differenza dilist.insert(0)che è O(n).- Usa
dequeper operazioni frequenti a entrambe le estremità.
🧠 Raccomandazioni prestazioni
| Situazione | Usare | Motivo |
|---|---|---|
| Memorizzare numeri, memoria critica | array.array | 2x meno memoria, accesso più veloce |
| Dati immutabili | tuple | Più veloce di list, più sicuro |
Verifiche frequenti x in collection | set / frozenset | O(1) vs O(n) di list |
| Operazioni a entrambe le estremità | deque | appendleft/popleft in O(1) |
| Dati strutturati, memoria critica | dataclass + __slots__ | Nessun __dict__, meno memoria |
| Contare frequenze | Counter | Ottimizzato per questo compito |
| Comportamento personalizzato | UserList / UserDict | Estensione sicura delle collezioni integrate |
📊 Confronto collezioni
| Tipo | Ordinato | Modificabile | Elementi unici | Accesso indice | Duplicati |
|---|---|---|---|---|---|
list | ✅ Sì | ✅ Sì | ❌ No | ✅ Sì | ✅ Sì |
tuple | ✅ Sì | ❌ No | ❌ No | ✅ Sì | ✅ Sì |
dict | ✅ Sì* | ✅ Sì | Solo chiavi | ❌ No | Valori: ✅ |
set | ❌ No | ✅ Sì | ✅ Sì | ❌ No | ❌ No |
frozenset | ❌ No | ❌ No | ✅ Sì | ❌ No | ❌ No |
SimpleNamespace | ✅ Sì (attr) | ✅ Sì | ❌ No (attr possono ripetersi semanticamente) | ❌ No | ✅ Sì |
namedtuple | ✅ Sì | ❌ No | ❌ No | ✅ Sì | ✅ Sì |
deque | ✅ Sì | ✅ Sì | ❌ No | ✅ Sì | ✅ Sì |
Counter | ❌ No | ✅ Sì | ❌ No | ❌ No (ma ha chiavi) | ✅ Sì |
defaultdict | ✅ Sì* | ✅ Sì | Solo chiavi | ❌ No | Valori: ✅ |
dataclass | ✅ Sì (campi) | ✅ Sì (se non frozen) | ❌ No | ❌ No | ✅ Sì |
UserList | ✅ Sì | ✅ Sì | ❌ No | ✅ Sì | ✅ Sì |
UserDict | ✅ Sì* | ✅ Sì | Solo chiavi | ❌ No | Valori: ✅ |
str | ✅ Sì | ❌ No | ❌ No | ✅ Sì | ✅ Sì |
bytes | ✅ Sì | ❌ No | ❌ No | ✅ Sì | ✅ Sì |
bytearray | ✅ Sì | ✅ Sì | ❌ No | ✅ Sì | ✅ Sì |
range | ✅ Sì | ❌ No | ❌ No | ✅ Sì | ❌ No |
array.array | ✅ Sì | ✅ Sì | ❌ No | ✅ Sì | ✅ Sì |
ChainMap | ✅ Sì* | ✅ Sì | Solo chiavi | ❌ No | Valori: ✅ |
Enum | ✅ Sì | ❌ No | ✅ Sì (membri) | ❌ No | ❌ No |
- — da Python 3.7,
dict,defaultdict,UserDict,ChainMapmantengono l’ordine di inserimento.
💡 Quando usare cosa?
| Compito | Collezione |
|---|---|
| Sequenza modificabile | list / deque / UserList / bytearray |
| Dati immutabili | tuple / namedtuple / frozenset / str / bytes |
| Ricerca veloce, rimozione duplicati | set / frozenset |
| Dati strutturati | dict / dataclass / SimpleNamespace / UserDict / TypedDict |
| Usabile come chiave di dict | frozenset |
Oggetti temporanei con accesso tramite . | SimpleNamespace / dataclass |
| Contare frequenze | Counter |
| Valori predefiniti per chiavi | defaultdict |
| Operazioni efficienti alle estremità | deque |
| Comportamento personalizzato lista | UserList |
| Comportamento personalizzato dict | UserDict |
| Dati binari | bytes / bytearray / array.array |
| Configurazioni con gerarchia | ChainMap |
| Costanti nominate | Enum |
| Sequenze lazy | range / generatori |