سطح مقدماتی (Beginner Level)
در پایتون، تقریباً همه چیز یک «شیء» (Object) است. شاید شنیده باشید که اعداد، رشتهها و لیستها شیء هستند، اما نکتهای که اغلب فراموش میشود این است که خود کلاسها نیز شیء هستند.
در این سطح، یاد میگیریم که متاکلاس (Metaclass) چیست و چگونه پایتون کلاسها را میسازد.
۱. کلاسها هم شیء هستند
وقتی کدی را اجرا میکنید که یک کلاس تعریف میکند، پایتون آن را در حافظه ایجاد میکند. این شیء (که همان کلاس است)، قابلیت نمونهسازی (Instantiation) دارد.
به مثال زیر دقت کنید که چگونه یک کلاس را مانند یک متغیر پاس میدهیم:
۲. نقش type به عنوان متاکلاس پیشفرض
در پایتون، تابعی به نام type() وجود دارد که دو کاربرد دارد:
- نمایش نوع یک شیء (مثلاً
type(5)). - ساخت پویا (Dynamic) یک کلاس جدید.
وقتی شما یک کلاس مینویسید، پایتون در پشت صحنه از type استفاده میکند تا آن کلاس را بسازد. در واقع type، متاکلاس پیشفرض تمام کلاسها در پایتون ۳ است.
ساختار استفاده از type برای ساخت کلاس:
type(name, bases, dict)
- name: نام کلاس (رشته).
- bases: توپل کلاسهای والد (برای ارثبری).
- dict: دیکشنری شامل متدها و ویژگیهای کلاس.
مثال: ساخت کلاس بدون واژه class
۳. زنجیره ساخت (Instance -> Class -> Metaclass)
رابطه بین این اجزا به صورت زیر است:
- یک نمونه (Instance) توسط یک کلاس (Class) ساخته میشود.
- یک کلاس (Class) توسط یک متاکلاس (Metaclass) ساخته میشود.
- متاکلاس پیشفرض،
typeاست.
# Example 3: Visualizing the chain (Snippet)
x = 10
print(type(x)) # Output: <class 'int'>
print(type(int)) # Output: <class 'type'>

سطح پیشرفته (Professional Level)
در سطح حرفهای، ما متاکلاسهای اختصاصی خودمان را میسازیم تا رفتار ساخت کلاسها را تغییر دهیم. این تکنیک در ساخت ORMها (مثل Django Models) یا اعتبارسنجی کد بسیار کاربرد دارد.
برای ساخت یک متاکلاس، باید کلاسی بسازید که از type ارثبری کند.
۱. متد __new__ در متاکلاس
مهمترین متد در متاکلاس __new__ است. این متد قبل از اینکه کلاس کاملاً ساخته شود اجرا میشود و به شما اجازه میدهد دیکشنری کلاس، نام یا والدین را تغییر دهید یا بررسی کنید.
آرگومانهای __new__ در متاکلاس عبارتند از:
mcs(خود متاکلاس).name(نام کلاس در حال ساخت).bases(والدین).attrs(ویژگیها و متدها).
مثال: اجبار کردن نامگذاری متدها (Validation)
فرض کنید میخواهیم تمام متدهای کلاسهایمان لزوماً با پیشوند my_ شروع شوند وگرنه خطا دهیم.
۲. الگوی Singleton با متاکلاس
یکی از بهترین روشها برای پیادهسازی دیزاین پترن Singleton (که تضمین میکند تنها یک نمونه از کلاس وجود داشته باشد)، استفاده از متاکلاس است. ما متد __call__ متاکلاس را بازنویسی میکنیم. وقتی شما MyClass() را صدا میزنید، در واقع __call__ متاکلاس اجرا میشود.
۳. تغییر خودکار ویژگیها (Auto-Modification)
متاکلاسها میتوانند کد را تغییر دهند. مثلاً میتوانیم تمام ویژگیهای متنی (String) یک کلاس را به صورت خودکار به حروف بزرگ تبدیل کنیم.
نکات فنی نهایی
- پیچیدگی: متاکلاسها قدرتمند اما پیچیده هستند. به قول تیم پیترز (Tim Peters): «اگر شک دارید که به متاکلاس نیاز دارید یا نه، یعنی به آن نیاز ندارید.»
- ارثبری: متاکلاسها نیز ارثبری میشوند. اگر کلاسی متاکلاس
Mداشته باشد، کلاسهای فرزند آن نیزMرا خواهند داشت. - تفاوت با دکوریتور کلاس: دکوریتورها روی کلاس ساخته شده نهایی اثر میگذارند، اما متاکلاسها روی فرآیند ساخت کلاس اثر دارند.