__slots__ ja muistin optimointi
Käyttäkää __slots__-määrettä instanssikohtaisen muistin kulutuksen vähentämiseen.
__slots__ ja muistin optimointi on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Python Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Python Academy-kurssilla on yhteensä 4 oppituntia.
Oletusarvoisen __dict__:n aiheuttama lisäkuormitus
Oletusarvoisesti jokainen Python-instanssi tallentaa attribuutit __dict__-sanakirjaan, mikä aiheuttaa huomattavan muistilisän — yleensä 200–400 tavua instanssia kohden.
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 bytes__slots__:n määrittäminen
Määritelkää __slots__ attribuuttinimien sekvenssinä. Python varaa sanakirjan sijaan kiinteän kokoisen taulukon, mikä säästää muistia.
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__Muistinsäästö
__slots__-määrittelyä käyttävä instanssi kuluttaa yleensä 30–50 % vähemmän muistia kuin sanakirjapohjainen instanssi — säästö on merkittävä, kun olioita luodaan miljoonia.
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)Ei __dict__:a oletusarvoisesti
Slots-luokalla ei ole __dict__-sanakirjaa, joten siihen ei voi lisätä mielivaltaisia attribuutteja luomisen jälkeen.
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__")) # False__dict__:n säilyttäminen __slots__:n kanssa
Sisällyttäkää "__dict__" __slots__-määrittelyyn, jos haluatte säilyttää instanssikohtaisen sanakirjan ja samalla määrittää yleiset attribuutit etukäteen slotteina.
class Hybrid:
__slots__ = ("x", "__dict__")
def __init__(self, x):
self.x = x
h = Hybrid(1)
h.extra = "dynamic" # allowed
print(h.extra)__weakref__ __slots__-määrittelyssä
Slots-luokat menettävät heikkojen viitteiden tuen. Lisätkää "__weakref__" __slots__-määrittelyyn, jos haluatte ottaa tuen uudelleen käyttöön.
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>Periytyminen ja __slots__
Jos yliluokka ei käytä __slots__-määrittelyä, aliluokka saa silti __dict__-sanakirjan. Täyden muistinsäästön saavuttamiseksi koko luokkahierarkian on määritettävä __slots__.
class Base:
__slots__ = ("x",)
class Child(Base):
__slots__ = ("y",) # no __dict__
class WithoutSlots(Base):
pass # gets __dict__ from objectMuistin käytön mittaaminen
Käyttäkää tracemalloc- tai pympler-kirjastoa todellisen muistin käytön mittaamiseen ennen __slots__-määrittelyn lisäämistä ja sen jälkeen.
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__ ja pickle-serialisointi
Slots-oliot voidaan pickle-serialisoida, jos määrittelette __getstate__- ja __setstate__-metodit, tai käyttämällä oletusarvoista pickle-protokollaa, joka käsittelee slotit automaattisesti Python 3:sta alkaen.
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 ja __slots__ — Python 3.10+
Välittäkää slots=True parametrina koristelijalle @dataclass, niin __slots__ luodaan automaattisesti.
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__")) # FalseMilloin __slots__-määrittelyä kannattaa käyttää
Käyttäkää __slots__-määrittelyä, kun instansseja luodaan miljoonia, muistia on rajallisesti tai attribuuttien käytön nopeus on kriittinen. Jättäkää se pois yleiskäyttöisistä luokista, joissa joustavuus on tärkeämpää.
# 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 attributesPikatarkistus
Mitä tapahtuu, kun slotted-instanssille yritetään määrittää attribuutti, jota ei ole lueteltu __slots__-määrittelyssä?
Kertaus
__slots__ korvaa instanssikohtaisen __dict__-sanakirjan kiinteällä taulukolla ja säästää 30–50 % muistia. Sisällyttäkää "__dict__" tai "__weakref__", jos tarvitsette niitä. Koko periytymisketjun on käytettävä __slots__-määrittelyä täyden säästön saavuttamiseksi. Käyttäkää Python 3.10:stä alkaen muotoa @dataclass(slots=True).
Opi Python tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 76
- Oppitunnit
- 320
Usein kysytyt kysymykset
Onko oppitunti ”__slots__ ja muistin optimointi” ilmainen?
Kyllä – oppitunnin ”__slots__ ja muistin optimointi” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Python Academy-kurssin, päivitä CoddyKit PROhon. Python Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”__slots__ ja muistin optimointi”?
Käyttäkää __slots__-määrettä instanssikohtaisen muistin kulutuksen vähentämiseen. Harjoittelet Python Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Python Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Python Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”__slots__ ja muistin optimointi”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Python Academy-oppitunnilla?
Kyllä. Jokainen Python Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Miten Python-luokat luodaan
- Mukautettujen metaluokkien kirjoittaminen
- Deskriptorit: __get__, __set__, __delete__
- __slots__ ja muistin optimointi