توی این قسمت، خیلی سریع و خلاصه میخوایم متد __new__ رو معرفی کنیم و به کاربردهای اون اشاره کنیم.
برای ساخت یک Instance از کلاس دو متد اصلی هستند که اجرا میشن. هر کدوم هم کار متفاوتی انجام میدن.
حالا برای روشن شدن مطلب میریم اولش static method رو تعریف کنیم و بعدش به خود متد __new__ میپردازیم.
این مفهوم در مقابل مفهوم دیگهای به اسم instance variable قرار میگیره. تو مثال زیر متد و attributeهای ما instance variable هستند.
کاری که کردیم این هست که یک instance از کلاس Math ساختیم و از تابع add استفاده کردیم. اما چی میشه اگر ازش Instance نسازیم و بخوایم ازش استفاده کنیم؟
خطا بالا داره میگه که انگار یک پارامتر کمتر به تابع add دادیم و بهمین خاطر معترض شده! بیایم instance رو دستی بهش پاس بدیم:
همم، پس اینجوری خوشحالتر شد. پس instance variableها بدون داشتن یک instance قابل استفاده نیستند.
اما میتونیم خوشحالی کلاس Math رو یک سطح هم بالاتر ببریم اگر کلا این متد رو جوری تعریف کنیم که نیاز به Instance ای نداشته باشه و امکان استفاده بدون ساخت Instance هم وجود داشته باشه.
اینجا با کمک دوست خوبمون staticmethod - که یک property ( یا به اصطلاح درستتر یک Descriptor) هست - به پایتون میگیم که نیازی نیست که instance اولین پارامتر ما باشه. در نتیجه بدون ساخت instance میتونیم ازش استفاده کنیم.
حالا چی مشه، اگر از اون یک Instance بسازیم؟ آیا باز هم قابل استفاده هست؟
به عنوان جمعبندی این بخش، ما به صراحتاً به پایتون گفتیم که این متد به صورت static method به کارش ادامه بده، اما بعضی توابع خاص (Magic methods) به صورت پیشفرض static method هستند، مثل __new__.
وقتی میگیم که __init__ تابع سازنده نیست به این خاطر هست که شما داخل __init__ به آبجکت دسترسی دارید. نشون به این نشون که:
همین نشون میده که انگار یکجای دیگه instance ما ساخته شده (چون پایتون خطا نداد که self وجود نداره!).
یک نمونه با هم ببینیم:
با توجه به خروجی بالا، میشه فهمید که cls همون کلاسی هست که قرار از روی اون یک instance ساخته بشه و مابقی هم پارامترهایی هستند که از ورودی دریافت کردیم. همونطور که گفتیم اگر چیزی داخل __new__ برنگردونیم (return)، متد __init__ اجرا نمیشه، در نتیجه توی مثال بالا سه خط آخر اصلا اجرا نشدهاند.
اگر بخواهیم رفتار نرمال متد __new__ رو نشون بدیم چیزی شبیه پایین میشه:
اینجا چه اتفاقی رخ داده؟ ما از سوپرکلاسمون خواهش کردیم که به جای ما یک instance بسازه و همچنین به صورت dynamic یک attribute به instance تازه ساخته شده اضافه کردیم (created_at).
چه مواقعی نیاز داریم که __new__ رو override کنیم؟
جواب.
یک مثال عملی رو با هم ببینیم و بحث رو تموم کنیم. اگر با ایدهی Singleton آشنا باشید میدونید که هدف اون ساخت کلاسی هست که فقط امکان ساخت یک instance ازش وجود داشته باشه. برای پیادهسازی این مفهوم روشهای مختلفی هست اما ما عمداً با کمک متد __new__ این مفهوم رو پیادهسازی میکنیم:
اینجا متد سازنده رو طوری تغییر دادیم که - عمداً - فقط بتونیم یک instance از کلاسمون بسازیم و هربار که تلاش کنیم چیز جدید بسازیم همون قبلی رو برگردونه.
اگر مثال یا تجربه شخصی استفاده از متد __new__ دارید اون رو حتماً با ما به اشتراک بذارید.
امیدوارم که از این مطلب خوشتون اومده باشه و چیزی ازش یاد گرفته باشید، اگر اینطور بوده حتما این مطلب با پایتون دوستهای دیگه به اشتراک بذارید. فعلاً!