0Pricing
Python Academy · درس

__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 4

dataclasses مع __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 يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. كيفية إنشاء فئات Python
  2. كتابة أصناف وصفية مخصصة
  3. واصفات الخصائص: __get__ و__set__ و__delete__
  4. __slots__ وتحسين الذاكرة
← العودة إلى Python Academy