ما هي metaclasses في Python؟ دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

الميتاكلاسات (Metaclasses) في Python هي فئات خاصة تقوم بإنشاء وإدارة الفئات الأخرى. بما أن كل شيء في Python هو كائن، بما في ذلك الفئات، يمكن اعتبار الميتاكلاسات على أنها "فئات للفئات". فهي توفر آلية للتحكم في عملية إنشاء الفئات وتعديل سلوكها في مرحلة التعريف.

كيفية عمل الميتاكلاسات

عندما يواجه Python تعريف فئة، فإنه يستخدم تلقائيًا الميتاكلاس type لإنشاء هذه الفئة. تبدو العملية كالتالي:

class MyClass:
    pass

داخليًا، ينفذ Python الأمر التالي:

MyClass = type('MyClass', (), {})

حيث:

  • 'MyClass' — اسم الفئة
  • () — مجموعة (tuple) الفئات الأم
  • {} — قاموس الخصائص والطرق (attributes and methods) للفئة

الميتاكلاس المدمج type هو المسؤول عن إنشاء جميع الفئات في Python بشكل افتراضي.

إنشاء ميتاكلاس خاص بك

يتم إنشاء الميتاكلاسات المخصصة عن طريق الوراثة من type وإعادة تعريف طرقه:

class MyMeta(type):
    def __new__(cls, name, bases, attrs):
        print(f"جارٍ إنشاء الفئة {name}")
        attrs['created_by_metaclass'] = True
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMeta):
    pass

print(MyClass.created_by_metaclass)  # True

الطرق الأساسية للميتاكلاسات

__new__

يتحكم في إنشاء الفئة. يتم استدعاؤه قبل __init__ ويعيد الفئة الجديدة:

class CreationMeta(type):
    def __new__(cls, name, bases, attrs):
        # تعديل الخصائص قبل إنشاء الفئة
        attrs['class_id'] = id(cls)
        return super().__new__(cls, name, bases, attrs)

__init__

يقوم بتهيئة الفئة التي تم إنشاؤها بالفعل:

class InitMeta(type):
    def __init__(cls, name, bases, attrs):
        print(f"تهيئة الفئة {name}")
        super().__init__(name, bases, attrs)

__call__

يحدد السلوك عند إنشاء نسخ (instances) من الفئة:

class CallMeta(type):
    def __call__(cls, *args, **kwargs):
        print(f"إنشاء نسخة من {cls.__name__}")
        return super().__call__(*args, **kwargs)

أمثلة عملية للتطبيق

تحويل الخصائص تلقائيًا إلى أحرف كبيرة

class UpperAttrMeta(type):
    def __new__(cls, name, bases, attrs):
        uppercase_attrs = {}
        for attr_name, attr_value in attrs.items():
            if not attr_name.startswith('__'):
                uppercase_attrs[attr_name.upper()] = attr_value
            else:
                uppercase_attrs[attr_name] = attr_value
        return super().__new__(cls, name, bases, uppercase_attrs)

class MyClass(metaclass=UpperAttrMeta):
    attr1 = 'value1'
    attr2 = 'value2'

print(hasattr(MyClass, 'ATTR1'))  # True
print(hasattr(MyClass, 'attr1'))  # False

تطبيق نمط Singleton

class SingletonMeta(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]

class DatabaseConnection(metaclass=SingletonMeta):
    def __init__(self):
        print("إنشاء اتصال بقاعدة البيانات")

db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True

التحقق من صحة بنية الفئات

class ValidatedMeta(type):
    def __new__(cls, name, bases, attrs):
        # التحقق من وجود طريقة إلزامية
        if 'process' not in attrs:
            raise TypeError(f"الفئة {name} يجب أن تحتوي على طريقة 'process'")
        return super().__new__(cls, name, bases, attrs)

class MyService(metaclass=ValidatedMeta):
    def process(self):
        pass  # هذا سيعمل بنجاح

المدونات

توصيات الكتب