💻 آخرین فرصت یادگیری برنامه‌نویسی با آفر ویژه قبل از افزایش قیمت در ۱۵ آذر ماه (🎁 به همراه یک هدیه ارزشمند )
۰ ثانیه
۰ دقیقه
۰ ساعت
۳ هادی خانزاده
قاعده ی mro
محمدعلی رضا حل شده توسط محمدعلی رضا

سلام

اگه یکی از کلاس‌ها از کلاس دیگه ای ارث بری کرده باشه؛ باید از  super برای init کردن method‌های parent استفاده کنیم؛

حالا چطوری از قاعده mro استفاده کنیم؟

تو فایل ضمیمه  کد و نمودار ساختار کلاس‌ها استفاده شده رو قرار دادم

 

سلااااااااااااااااام

ببین من جمله اولت رو یه مقدار تصحیح میکنم:

اگر یک کلاس از کلاس یا کلاس‌های دیگه ای ارث بری کرده باشه. میتونیم از super داخل متدهای کلاس فرزند استفاده کنیم تا متدهای کلاس پدر رو اجرا کنیم.

وقتی یه کلاس فرزند داریم که داره از کلاسی (که بهش میگیم کلاس پدر) ارث بری میکنه و کلاس پدر متد __init__ داره و حالا میخوایم تو کلاس فرزند متد __init__ رو بازنویسی (overwrite) کنیم، اکثرا لازم میشه که تو __init__ کلاس فرزند متد __init__ پدر یعنی super رو صدا بزنیم. یه تیکه کد برای مثال ببینیم که بهتر منظور این پاراگراف رو بفهمیم:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
class Student(Person):
    def __init__(self, name, age, grade):
        super().__init__(name, age)
        self.grade = grade
s1 = Student("ali", "reza", 20)

 

قاعده MRO رو لازمه که بدونیم که وقتی داریم تو کلاس‌ها مون ارث بری انجام میدیم حواسمون باشه که چه اتفاقی داره می‌افته و method‌ها و attribute هارو تو کلاس‌های فرزند و پدر چطور بنویسیم. مخصوصا وقتی داریم Multiple Inheritance انجام میدیم.

 

حالا طبق این حرف‌ها و جلسه ی این تاپیک، بنظرم کدت باید اینطور اصلاح بشه:

class HouseInf:
    def __init__(self, age, area, rooms, address, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.age = age
        self.area = area
        self.rooms = rooms
        self.address = address
class Apartment(HouseInf):
    def __init__(self, floor, parking, elevator=True, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.parking = parking
        self.elevator = elevator
        self.floor = floor
class Sale:
    def __init__(self, price, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.price = price
class ApartmentSale(Apartment, Sale):
    def __str__(self):
        return f"{self.floor}, {self.age}"
if __name__ == '__main__':
    apartment_sale = ApartmentSale(floor=10, age=5, parking=1, elevator=True, rooms=3, address="tehran", area=120,
                                   price=500000)
    print(apartment_sale)

 

اگر باز سوالی داشتی یا نکته ای بود تو همین تاپیک بگو

بهترین پاسخ
محمدعلی رضا ۲۰ آبان ۱۳۹۹، ۰۵:۵۰

سلام علیرضا خیلی ممنون از جواب کاملی که دادی با اینکه سوالم نامفهوم بود

مشکل من این بود که بعد از صدا زدن برای مقدار دهی؛ مقدار دهدی کلاس Apartment که تموم شد وارد کلاس Sale نمیشد

که کلید حل این مشکل super ای بود که به HouseInf اضافه شد درسته؟

که وقتی وارد HouseInf شد بعد از مقدار دهی متوجه بشه که init تموم نشد بره بعدی که بعدی میشه Sale

اما چرا توی کلاس Sale هم از super استفاده کردی؟

 

 

هادی خانزاده ۲۰ آبان ۱۳۹۹، ۰۷:۴۰

بله درسته.
من چند تا کار انجام دادم:

  1. توی همه __init__‌های کلاس‌ها یه بار متد __init__ پدرشون یعنی super رو صدا زدم. و توی کلاس Sale صدا زدن __init__ پدرش super هیچ تاثیری نداره ولی یه convention و قرار داد هستش که بعضی از برنامه نویس‌های پایتون رعایت میکنن مثلا خود کلاس object که همه ی کلاس‌های پایتون ازش ارث بری میکنن هم این قرارداد رو رعایت کرده.
  2. ورودی‌های __init__‌های کلاس هات رو یه مقدار قشنگ‌تر نوشتم.
  3. وقت ساخت ابجکت که از کللاس ApartmentSale استفاده کردی بهش price رو نداده بودی که من دادم.

برای فهمیدن تفاوت ۲ تا فایل هم میتونی از دستور diff یا git diff استفاده کنی که دقیقا بفهمی من چه تغییراتی تو کدت دادم. (در مورد این دستورات هم میتونی تو گوگل سرچ کنی)

محمدعلی رضا ۲۰ آبان ۱۳۹۹، ۰۸:۰۱