__slots__ e ottimizzazione della memoria
Utilizzi __slots__ per ridurre l'overhead di memoria per istanza.
__slots__ e ottimizzazione della memoria è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.
L'overhead predefinito di __dict__
Per impostazione predefinita, ogni istanza Python memorizza gli attributi in un dizionario __dict__, che comporta un overhead significativo in termini di memoria — in genere 200-400 byte per istanza.
import sys
class Point:
def __init__(self, x, y): self.x, self.y = x, y
p = Point(1, 2)
print(sys.getsizeof(p.__dict__)) # ~200 bytesDichiarare __slots__
Definisca __slots__ come una sequenza di nomi di attributi. Python alloca un array di dimensione fissa invece di un dizionario, risparmiando memoria.
class SlottedPoint:
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
p = SlottedPoint(1, 2)
print(p.x, p.y) # 1 2
# p.z = 3 # AttributeError: no __dict__Risparmio di memoria
Con __slots__, ogni istanza utilizza in genere il 30-50% di memoria in meno rispetto a un'istanza basata su un dizionario — un risparmio significativo quando si creano milioni di oggetti.
import sys
class Reg:
def __init__(self, x, y): self.x, self.y = x, y
class Slotted:
__slots__ = ("x","y")
def __init__(self, x, y): self.x, self.y = x, y
print(sys.getsizeof(Reg(1,2))) # ~56 bytes + ~200 dict
print(sys.getsizeof(Slotted(1,2))) # ~56 bytes (no dict)Nessun __dict__ per impostazione predefinita
Una classe con slot non dispone di __dict__, quindi non è possibile aggiungere attributi arbitrari dopo la creazione.
class Config:
__slots__ = ("host", "port")
def __init__(self, h, p): self.host, self.port = h, p
c = Config("localhost", 8080)
# c.debug = True # AttributeError
print(hasattr(c, "__dict__")) # FalseMantenere __dict__ con __slots__
Includa "__dict__" in __slots__ per mantenere un dizionario per istanza, continuando a dichiarare in anticipo gli attributi comuni come slot.
class Hybrid:
__slots__ = ("x", "__dict__")
def __init__(self, x):
self.x = x
h = Hybrid(1)
h.extra = "dynamic" # allowed
print(h.extra)__weakref__ in __slots__
Le classi con slot perdono il supporto ai riferimenti deboli. Aggiunga "__weakref__" a __slots__ per riattivarlo.
import weakref
class Node:
__slots__ = ("value", "__weakref__")
def __init__(self, v): self.value = v
n = Node(42)
ref = weakref.ref(n)
print(ref()) # <Node object>Ereditarietà e __slots__
Se una classe genitore non utilizza __slots__, la classe figlia dispone comunque di un __dict__. Per ottenere il massimo risparmio, l'intera gerarchia deve definire __slots__.
class Base:
__slots__ = ("x",)
class Child(Base):
__slots__ = ("y",) # no __dict__
class WithoutSlots(Base):
pass # gets __dict__ from objectMisurare la memoria
Utilizzi tracemalloc o pympler per misurare l'utilizzo effettivo della memoria prima e dopo l'aggiunta di __slots__.
import tracemalloc
tracemalloc.start()
points = [SlottedPoint(i, i) for i in range(100_000)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Peak: {peak/1024/1024:.1f} MB")__slots__ e pickling
Gli oggetti con slot possono essere sottoposti a pickling se si definiscono __getstate__ e __setstate__, oppure si utilizza il protocollo pickle predefinito, che gestisce automaticamente gli slot a partire da Python 3.
import pickle
class Point:
__slots__ = ("x", "y")
def __init__(self, x, y): self.x, self.y = x, y
p = Point(3, 4)
data = pickle.dumps(p)
p2 = pickle.loads(data)
print(p2.x, p2.y) # 3 4dataclasses con __slots__ — Python 3.10+
Passi slots=True a @dataclass per generare automaticamente __slots__.
from dataclasses import dataclass
@dataclass(slots=True)
class Vector:
x: float
y: float
v = Vector(1.0, 2.0)
print(v.x, v.y) # 1.0 2.0
print(hasattr(v, "__dict__")) # FalseQuando utilizzare __slots__
Utilizzi __slots__ quando deve creare milioni di istanze, la memoria è limitata oppure la velocità di accesso agli attributi è fondamentale. Lo eviti nelle classi di uso generale, quando la flessibilità è più importante.
# Good candidates:
# - Nodes in a large graph or tree
# - Records in a large dataset
# - High-frequency event objects
# Bad candidates:
# - Configuration objects added to ad-hoc
# - Classes that mix-in dynamic attributesVerifica rapida
Cosa accade quando si prova a impostare, in un'istanza con slot, un attributo non elencato in __slots__?
Riepilogo
__slots__ sostituisce il __dict__ per istanza con un array di dimensione fissa, risparmiando il 30-50% di memoria. Includa "__dict__" o "__weakref__" se ne ha bisogno. Per ottenere il massimo risparmio, l'intera catena di ereditarietà deve utilizzare __slots__. In Python 3.10+ utilizzi @dataclass(slots=True).
Domande Frequenti
La lezione «__slots__ e ottimizzazione della memoria» è gratuita?
Sì — il testo completo di «__slots__ e ottimizzazione della memoria» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.
Cosa imparerò in «__slots__ e ottimizzazione della memoria»?
Utilizzi __slots__ per ridurre l'overhead di memoria per istanza. Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Python Academy?
Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «__slots__ e ottimizzazione della memoria»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Python Academy?
Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Come vengono create le classi Python
- Scrittura di metaclassi personalizzate
- Descriptor: __get__, __set__, __delete__
- __slots__ e ottimizzazione della memoria