وراثت مفید است، اما میتوانید با استفاده مجدد از کدهای کلاسهای پایه، پتانسیل کامل آن را باز کنید.
نکات کلیدی
- تابع super() پایتون به شما امکان می دهد متدهای سوپرکلاس را از یک زیر کلاس فراخوانی کنید و پیاده سازی وراثت و نادیده گرفتن متد را آسان تر می کند.
- تابع super() ارتباط نزدیکی با Method Resolution Order (MRO) در پایتون دارد که ترتیب جستجوی کلاسهای اجداد را برای متدها یا ویژگیها تعیین میکند.
- استفاده از super() در سازنده کلاس، یک روش معمول برای مقداردهی اولیه ویژگی های مشترک در کلاس والد و ویژگی های خاص تر در کلاس فرزند است. عدم استفاده از super() می تواند منجر به عواقب ناخواسته شود، مانند از دست دادن مقداردهی اولیه مشخصه.
یکی از ویژگی های اصلی پایتون الگوی OOP آن است که می توانید از آن برای مدل سازی موجودیت های دنیای واقعی و روابط آنها استفاده کنید.
هنگام کار با کلاسهای پایتون، اغلب از وراثت استفاده میکنید و ویژگیها یا متدهای یک سوپرکلاس را نادیده میگیرید. پایتون یک تابع super() ارائه میکند که به شما امکان میدهد متدهای سوپرکلاس را از زیر کلاس فراخوانی کنید.
super() چیست و چرا به آن نیاز دارید؟
با استفاده از وراثت، می توانید یک کلاس پایتون جدید بسازید که ویژگی های یک کلاس موجود را به ارث می برد. همچنین میتوانید روشهای سوپرکلاس را در زیر کلاس نادیده بگیرید و پیادهسازیهای جایگزین را ارائه دهید. با این حال، ممکن است بخواهید از عملکرد جدید علاوه بر عملکرد قدیمی، به جای آن استفاده کنید. در این مورد، super() مفید است.
شما می توانید از تابع super() برای دسترسی به ویژگی های superclass و فراخوانی متدهای superclass استفاده کنید. Super برای برنامه نویسی شی گرا ضروری است زیرا پیاده سازی وراثت و overriding متد را آسان تر می کند.
super() چگونه کار می کند؟
در داخل، super() ارتباط نزدیکی با ترتیب تفکیک روش (MRO) در پایتون دارد که الگوریتم خطی سازی C3 آن را تعیین می کند.
در اینجا نحوه عملکرد super() آمده است:
- کلاس و نمونه فعلی را تعیین کنید: وقتی super() را در داخل متدی از یک زیر کلاس فراخوانی می کنید، پایتون به طور خودکار کلاس فعلی (کلاس حاوی متدی که super() را فراخوانی می کند) و نمونه آن کلاس (یعنی self) را مشخص می کند. .
- superclass را تعیین کنید: super() دو آرگومان می گیرد – کلاس فعلی و نمونه – که نیازی به تصویب صریح آنها ندارید. از این اطلاعات برای تعیین سوپرکلاس برای واگذاری فراخوانی متد استفاده می کند. این کار را با بررسی سلسله مراتب کلاس و MRO انجام می دهد.
- فراخوانی متد در Superclass: هنگامی که superclass مشخص شد، super() به شما اجازه می دهد تا متدهای آن را به گونه ای فراخوانی کنید که گویی مستقیماً آنها را از زیر کلاس فراخوانی می کنید. این به شما امکان میدهد تا روشها را در حالی که هنوز از پیادهسازی اصلی سوپرکلاس استفاده میکنید، گسترش دهید یا نادیده بگیرید.
استفاده از super() در یک کلاس سازنده
استفاده از super() در سازنده کلاس یک روش معمول است، زیرا اغلب می خواهید ویژگی های مشترک را در کلاس والد و ویژگی های خاص تر را در فرزند مقداردهی کنید.
برای نشان دادن این موضوع، یک کلاس پایتون به نام Father تعریف کنید که کلاس Son از آن به ارث می برد:
class Father:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
class Son(Father):
def __init__(self, first_name, last_name, age, hobby):
# Call the parent class constructor (Father)
super().__init__(first_name, last_name)
self.age = age
self.hobby = hobby
def get_info(self):
return f"Son's Name: {self.first_name} {self.last_name}, \
Son's Age: {self.age}, Son's Hobby: {self.hobby}"
# Create an instance of the Son class
son = Son("Pius", "Effiong", 25, "Playing Guitar")
# Access attributes
print(son.get_info())
در داخل سازنده Son، فراخوانی به super().init() سازنده کلاس Father را فراخوانی میکند و first_name و last_name را به عنوان پارامتر ارسال میکند. این تضمین میکند که کلاس Father همچنان میتواند ویژگیهای نام را به درستی تنظیم کند، حتی روی یک شی Son.
اگر super() را در سازنده کلاس فراخوانی نکنید، سازنده کلاس والد آن اجرا نخواهد شد. این می تواند منجر به عواقب ناخواسته شود، مانند از دست دادن مقدار اولیه مشخصه یا تنظیم ناقص حالت کلاس والد:
...
class Son(Father):
def __init__(self, first_name, last_name, age, hobby):
self.age = age
self.hobby = hobby
...
اگر اکنون سعی کنید متد get_info را فراخوانی کنید، یک AttributeError ایجاد می کند زیرا ویژگی های self.first_name و self.last_name مقداردهی اولیه نشده اند.
استفاده از super() در Class Methods
شما می توانید از super() در روش های دیگر، به غیر از سازنده ها، به همین روش استفاده کنید. این به شما امکان می دهد رفتار متد superclass را گسترش دهید یا لغو کنید.
class Father:
def speak(self):
return "Hello from Father"
class Son(Father):
def speak(self):
# Call the parent class's speak method using super()
parent_greeting = super().speak()
return f"Hello from Son\n{parent_greeting}"
# Create an instance of the Son class
son = Son()
# Call the speak method of the Son class
son_greeting = son.speak()
print(son_greeting)
کلاس Son از پدر ارث می برد و روش صحبت خود را دارد. متد speak از کلاس Son از super().speak() برای فراخوانی متد speak کلاس Father استفاده می کند. این به آن اجازه می دهد تا پیام کلاس والد را در بر گیرد و در عین حال آن را با پیامی خاص برای کلاس فرزند گسترش دهد.
عدم استفاده از super() در روشی که دیگری را نادیده می گیرد به این معنی است که عملکرد موجود در متد کلاس والد اعمال نمی شود. این منجر به جایگزینی کامل رفتار روش می شود، که می تواند منجر به رفتاری شود که شما قصد نداشتید.
درک ترتیب وضوح روش
ترتیب وضوح روش (MRO) ترتیبی است که پایتون در هنگام دسترسی به یک متد یا یک ویژگی، کلاسهای اجداد را جستجو میکند. MRO به پایتون کمک می کند تا زمانی که سلسله مراتب وراثت چندگانه وجود دارد، کدام متد را فراخوانی کند.
class Nigeria():
def culture(self):
print("Nigeria's culture")
class Africa():
def culture(self):
print("Africa's culture")
وقتی یک نمونه از کلاس Lagos ایجاد میکنید و متد فرهنگ را فراخوانی میکنید، این اتفاق میافتد:
- پایتون با جستجوی متد فرهنگ در خود کلاس لاگوس شروع می کند. اگر آن را پیدا کرد، متد را فراخوانی می کند. اگر نه، به مرحله دو می رود.
- اگر متد فرهنگ را در کلاس لاگوس پیدا نکرد، پایتون به کلاسهای پایه به ترتیبی که در تعریف کلاس ظاهر میشوند نگاه میکند. در این مورد، لاگوس ابتدا از آفریقا و سپس از نیجریه به ارث می برد. بنابراین، پایتون ابتدا به دنبال روش فرهنگ در آفریقا خواهد بود.
- اگر روش فرهنگ را در کلاس آفریقا پیدا نکرد، پایتون در کلاس نیجریه جستجو می کند. این رفتار تا زمانی که به انتهای سلسله مراتب برسد ادامه می یابد و اگر نتواند متد را در هیچ یک از سوپرکلاس ها پیدا کند، خطا می دهد.
خروجی ترتیب وضوح روش لاگوس را نشان می دهد که از چپ به راست شروع می شود.
دام های رایج و بهترین شیوه ها
هنگام کار با super()، برخی از مشکلات رایج وجود دارد که باید از آنها اجتناب کنید.
- به ترتیب حل و فصل روش، به ویژه در سناریوهای ارث چندگانه، توجه داشته باشید. اگر نیاز به استفاده از وراثت چندگانه پیچیده دارید، باید با الگوریتم خطی سازی C3 که پایتون برای تعیین MRO استفاده می کند، آشنا باشید.
- از وابستگی های دایره ای در سلسله مراتب کلاس خود اجتناب کنید، که می تواند منجر به رفتار غیرقابل پیش بینی شود.
- کد خود را به وضوح مستند کنید، به خصوص زمانی که از super() در سلسله مراتب کلاس های پیچیده استفاده می کنید تا برای توسعه دهندگان دیگر قابل درک تر شود.
از super() به روش درست استفاده کنید
تابع super() پایتون یک ویژگی قدرتمند است وقتی که با وراثت و نادیده گرفتن متد کار می کنید. درک نحوه عملکرد super() و پیروی از بهترین شیوه ها به شما امکان می دهد کدهای قابل نگهداری و کارآمدتری را در پروژه های پایتون خود ایجاد کنید.