سرمایه گذاری متفاوت در سال نو 🍎🌱 ۳۵٪ تخفیف نوروزی ➕ حضور رایگان در مسترمایند نخبگان صنعت نرم‌افزار 💻✅
۰ ثانیه
۰ دقیقه
۰ ساعت
۱ گیسو
نگرفتن خروجی مورد نظر
جامعه پایتون (وب) ایجاد شده در ۲۵ اسفند ۱۴۰۳

سلام وقت بخیر چرا در کد من وقتی جای کلاس sellو Apartement را عوض میکنیم خروجی مورد نظر رو نمی‌تونم در یافت کنم وقتی اول کلاس sell رو مینویسم و بعدکلاس Apartementرو خروجی صحیح هست ولی جاهاشون رو که عوض میکنم خروجی به صورت زیر هست:

price: price_per_meter     discountable: discountable     convertable: convertable

 

 

قسمتی از کد‌ها به شکل زیر هست:

 

 

class Apartement(EstateAbstract):
    def __init__(self, has_elevator, has_parking, floor, *args, **kwargs):
        self.has_elevator = has_elevator
        self.has_parking = has_parking
        self.floor = floor
        super().__init__(*args, *kwargs)

    def show_description(self):
        print(f"Apartement: {self.id}\t area:{self.has_parking}")
 

 

class Sell(ABC):
    def __init__(self, price_per_meter, discountable, convertable, *args, **kwargs):
        self.price_per_meter = price_per_meter
        self.discountable = discountable
        self.convertable = convertable
        super().__init__(*args, **kwargs)

    def show_price(self):
        print(f"price: {self.price_per_meter}\t discountable: {self.discountable}\t convertable: {self.convertable}")
 

class ApartementSell(BaseClass,Sell,Apartement ):
    def show_detail(self):
        self.show_description()
        self.show_price()
reg1 = Region(name='R1')
apt1 = Apartement(has_elevator=True, has_parking=True, floor=2,user=User.objects_list[0], area=80, rooms_count=2,
                  built_year=1383,region=reg1, address="some text....")

 

apartement_sell = ApartementSell( has_elevator=True, has_parking=True, floor=2,user=User.objects_list[3], area=20, rooms_count=3,
                                  built_year=1354,region=reg1, address="some text....",
                                 price_per_meter=450 , discountable=True, convertable=False)
apartement_sell.show_detail()

 

خب ببین، مشکلت ریشه تو ترتیب ارث‌بری (MRO - Method Resolution Order) توی پایتون داره. یعنی اینکه کلاس‌ها به چه ترتیبی از همدیگه ارث‌بری کنن و super() چجوری مقدارها رو پاس بده.

چرا وقتی Sell رو اول می‌نویسی درست کار می‌کنه؟

وقتی Sell رو قبل از Apartement تو کلاس ApartementSell می‌ذاری:

class ApartementSell(BaseClass, Sell, Apartement):
  • super().__init__(*args, **kwargs) توی Sell اجرا می‌شه، بعد مقادیر باقی‌مونده می‌ره تو Apartement و همه‌چی اوکیه.
  • Sell پارامترهای خودشو (price_per_meter, discountable, convertable) برمی‌داره و بقیه رو پاس می‌ده.

حالا چرا وقتی Apartement رو قبل از Sell می‌ذاری، خروجی خراب می‌شه؟

class ApartementSell(BaseClass, Apartement, Sell):
  • اول Apartement مقداردهی می‌شه، بعدش super() رو صدا می‌زنه.
  • اما Apartement اصلاً price_per_meter, discountable, convertable رو نمی‌شناسه، پس اونا تو kwargs می‌مونن.
  • وقتی Sell می‌رسه، انتظار داره این مقادیر تو kwargs باشن، ولی نیستن! در نتیجه خروجی خراب می‌شه.

چطور درستش کنیم؟

  1. بهترین و راحت‌ترین راه:
    ترتیب ارث‌بری رو تغییر نده! Sell رو قبل از Apartement بذار، مثل قبل:

    class ApartementSell(BaseClass, Sell, Apartement):
    

    اینجوری همه‌چی مثل ساعت کار می‌کنه!

  2. اگه مجبوری Apartement رو قبل از Sell بذاری:
    باید کاری کنی که Apartement پارامترهای Sell رو حذف نکنه. راهش اینه که مقدارهای خاص رو از kwargs برداری:

    class Apartement(EstateAbstract):
        def __init__(self, has_elevator, has_parking, floor, *args, **kwargs):
            self.has_elevator = has_elevator
            self.has_parking = has_parking
            self.floor = floor
            super().__init__(*args, **kwargs)  # ارسال بقیه مقادیر
    class Sell(ABC):
        def __init__(self, price_per_meter, discountable, convertable, *args, **kwargs):
            self.price_per_meter = price_per_meter
            self.discountable = discountable
            self.convertable = convertable
            super().__init__(*args, **kwargs)  # ارسال بقیه مقادیر
    

جمع‌بندی:
مشکلت اینه که وقتی Apartement رو اول قرار می‌دی، kwargs رو درست پاس نمی‌ده و Sell مقدارهای خودش رو از دست می‌ده. یا Sell رو جلوتر بذار، یا kwargs.pop() استفاده کن تا مقدارهای لازم رو تو کلاس درست پردازش کنی.

Reza Mobaraki ۲۵ اسفند ۱۴۰۳، ۱۷:۱۱