Python Academy · Pelajaran

__slots__ dan Pengoptimuman Memori

Gunakan __slots__ untuk mengurangkan lebihan memori bagi setiap contoh.

Pelajaran 4 daripada 413 langkah

__slots__ dan Pengoptimuman Memori ialah pelajaran Python Academy percuma di CoddyKit. Ini ialah pelajaran 4 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Python Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Python Academy merangkumi sejumlah 4 pelajaran.

Overhed Lalai __dict__

Secara lalai, setiap instans Python menyimpan atribut dalam kamus __dict__, yang mempunyai overhed memori yang ketara — biasanya 200–400 bait bagi setiap instans.

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

Mengisytiharkan __slots__

Takrifkan __slots__ sebagai jujukan nama atribut. Python memperuntukkan tatasusunan saiz tetap dan bukannya kamus, sekali gus menjimatkan memori.

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__

Penjimatan Memori

Dengan __slots__, setiap instans biasanya menjimatkan 30–50% memori berbanding instans berasaskan kamus — amat ketara apabila mencipta jutaan objek.

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)

Tiada __dict__ Secara Lalai

Kelas berslot tidak mempunyai __dict__, jadi anda tidak boleh menambah atribut sewenang-wenangnya selepas penciptaan.

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

Mengekalkan __dict__ dengan __slots__

Sertakan "__dict__" dalam __slots__ untuk mengekalkan kamus bagi setiap instans, sambil mengisytiharkan atribut umum terlebih dahulu sebagai slot.

class Hybrid:
    __slots__ = ("x", "__dict__")

    def __init__(self, x):
        self.x = x

h = Hybrid(1)
h.extra = "dynamic"   # allowed
print(h.extra)

__weakref__ dalam __slots__

Kelas berslot kehilangan sokongan rujukan lemah. Tambahkan "__weakref__" pada __slots__ untuk mendayakannya semula.

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>

Pewarisan dan __slots__

Jika kelas induk tidak menggunakan __slots__, kelas anak masih mendapat __dict__. Untuk penjimatan penuh, seluruh hierarki mesti mentakrifkan __slots__.

class Base:
    __slots__ = ("x",)

class Child(Base):
    __slots__ = ("y",)   # no __dict__

class WithoutSlots(Base):
    pass   # gets __dict__ from object

Menanda Aras Memori

Gunakan tracemalloc atau pympler untuk mengukur penggunaan memori sebenar sebelum dan selepas menambahkan __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")

Penyirian dan __slots__

Objek berslot boleh disiri jika anda mentakrifkan __getstate__ dan __setstate__, atau menggunakan protokol pickle lalai yang mengendalikan slot secara automatik mulai 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 4

dataclass dengan __slots__ — Python 3.10+

Hantar slots=True kepada @dataclass untuk menjana __slots__ secara automatik.

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__"))   # False

Bila Perlu Menggunakan __slots__

Gunakan __slots__ apabila anda mencipta jutaan instans, memori terhad atau kelajuan capaian atribut amat penting. Jangan gunakannya untuk kelas tujuan umum apabila fleksibiliti lebih penting.

# 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 attributes

Semakan Pantas

Apakah yang berlaku apabila anda cuba menetapkan atribut yang tidak disenaraikan dalam __slots__ pada instans berslot?

Rumusan

__slots__ menggantikan __dict__ bagi setiap instans dengan tatasusunan tetap, lalu menjimatkan 30–50% memori. Sertakan "__dict__" atau "__weakref__" jika anda memerlukannya. Seluruh rantaian pewarisan mesti menggunakan __slots__ untuk penjimatan penuh. Dalam Python 3.10+, gunakan @dataclass(slots=True).

Percuma untuk bermula

Pelajari Python dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
76
Pelajaran
320

Soalan Lazim

Adakah pelajaran “__slots__ dan Pengoptimuman Memori” percuma?

Ya — teks penuh “__slots__ dan Pengoptimuman Memori” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Python Academy, tingkat taraf kepada CoddyKit PRO. Kursus Python Academy merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “__slots__ dan Pengoptimuman Memori”?

Gunakan __slots__ untuk mengurangkan lebihan memori bagi setiap contoh. Anda berlatih Python Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Python Academy?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Python Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 4 daripada 4.

Berapa lamakah pelajaran “__slots__ dan Pengoptimuman Memori” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Python Academy ini?

Ya. Setiap pelajaran Python Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Cara Kelas Python Dicipta
  2. Menulis Metakelas Tersuai
  3. Penerang: __get__, __set__, __delete__
  4. __slots__ dan Pengoptimuman Memori
← Kembali ke Python Academy