__slots__ وتحسين الذاكرة
استخدم __slots__ لتقليل استهلاك الذاكرة لكل كائن
__slots__ وتحسين الذاكرة درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.
النفقات الإضافية الافتراضية لـ __dict__
يخزّن كل مثيل من مثيلات Python سماته افتراضيًا في قاموس __dict__، ما يسبب نفقات إضافية كبيرة على الذاكرة — تتراوح عادةً بين 200 و400 بايت لكل مثيل.
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__
عرّف __slots__ على أنه تسلسل من أسماء السمات. تخصص Python مصفوفة ثابتة الحجم بدلًا من القاموس، مما يوفر الذاكرة.
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__توفير الذاكرة
باستخدام __slots__، يوفر كل مثيل عادةً نسبة تتراوح بين 30% و50% من الذاكرة مقارنةً بمثيل يعتمد على قاموس، وهو توفير مهم عند إنشاء ملايين الكائنات.
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)لا يوجد __dict__ افتراضيًا
لا تحتوي الفئة التي تستخدم __slots__ على __dict__، لذلك لا يمكنك إضافة سمات عشوائية بعد الإنشاء.
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__ مع __slots__
ضمّن "__dict__" في __slots__ للاحتفاظ بقاموس خاص بكل مثيل، مع الاستمرار في التصريح مسبقًا عن السمات الشائعة باعتبارها خانات.
class Hybrid:
__slots__ = ("x", "__dict__")
def __init__(self, x):
self.x = x
h = Hybrid(1)
h.extra = "dynamic" # allowed
print(h.extra)__weakref__ في __slots__
تفقد الفئات التي تستخدم الخانات دعم المراجع الضعيفة. أضف "__weakref__" إلى __slots__ لإعادة تفعيله.
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>الوراثة و__slots__
إذا كانت الفئة الأصلية لا تستخدم __slots__، فستظل الفئة الابنة تحصل على __dict__. ولتحقيق التوفير الكامل، يجب أن تعرّف جميع الفئات في التسلسل الهرمي __slots__.
class Base:
__slots__ = ("x",)
class Child(Base):
__slots__ = ("y",) # no __dict__
class WithoutSlots(Base):
pass # gets __dict__ from objectقياس الذاكرة
استخدم tracemalloc أو pympler لقياس الاستخدام الفعلي للذاكرة قبل إضافة __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__ والتسلسل
يمكن إجراء التسلسل للكائنات التي تستخدم الخانات إذا عرّفت __getstate__ و__setstate__، أو استخدمت بروتوكول pickle الافتراضي الذي يتعامل مع __slots__ تلقائيًا بدءًا من 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 مع __slots__ — Python 3.10+
مرّر slots=True إلى @dataclass لإنشاء __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__")) # Falseمتى تستخدم __slots__
استخدم __slots__ عند إنشاء ملايين المثيلات، أو عندما تكون الذاكرة محدودة، أو عندما تكون سرعة الوصول إلى السمات أمرًا بالغ الأهمية. تجنّبه في الفئات ذات الاستخدام العام عندما تكون المرونة أهم.
# 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تحقق سريع
ماذا يحدث عند محاولة تعيين سمة غير مدرجة في __slots__ لمثيل يستخدم الخانات؟
مراجعة
يستبدل __slots__ قاموس __dict__ الخاص بكل مثيل بمصفوفة ثابتة، مما يوفر 30% إلى 50% من الذاكرة. ضمّن "__dict__" أو "__weakref__" إذا كنت بحاجة إليهما. يجب أن يستخدم تسلسل الوراثة بأكمله __slots__ لتحقيق التوفير الكامل. في Python 3.10+ استخدم @dataclass(slots=True).
الأسئلة الشائعة
هل درس «__slots__ وتحسين الذاكرة» مجاني؟
نعم — نص درس «__slots__ وتحسين الذاكرة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.
ماذا ستتعلم في «__slots__ وتحسين الذاكرة»؟
استخدم __slots__ لتقليل استهلاك الذاكرة لكل كائن تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟
لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «__slots__ وتحسين الذاكرة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟
نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- كيفية إنشاء فئات Python
- كتابة أصناف وصفية مخصصة
- واصفات الخصائص: __get__ و__set__ و__delete__
- __slots__ وتحسين الذاكرة