【问题标题】:Overriding python method to return object of correct class with extended data覆盖python方法以返回具有扩展数据的正确类的对象
【发布时间】:2020-04-10 19:39:39
【问题描述】:

假设我有一个类似的python类:

class Meal(object):
   def __init__(self, starter, main="steak"):
       self.starter = starter
       self.main = main

   def new_meal_eaten_starter(self):
       return Meal("Eaten-%s" % self.starter, main=self.main)

   def __repr__(self):
       return "%s %s" % (self.starter, self.main)

现在我想继承这个类,添加一些数据:

class MealWithDessert(Meal):
    def __init__(self, dessert, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.dessert = dessert

    def __repr__(self):
        return "%s %s %s" % (self.starter, self.main, self.dessert)

这当然会发生:

>>> x = MealWithDessert("cake", "salad", "pizza")
salad pizza cake
>>> x.new_meal_eaten_starter()
eaten-salad pizza

当然我想看的是吃沙拉披萨蛋糕。 我可以通过重写方法来使用基本方法来解决这个问题:

    def new_meal_eaten_starter(self):
        new_meal_no_dessert = super().new_eaten_starter()
        new_meal = MealWithDessert(self.dessert, new_meal_no_dessert.starter, main=new_meal_no_dessert.main)

    return new_meal

... 但这该死的丑陋。或者通过基本上复制基本方法(违反 DRY):

def new_meal_eaten_starter(self):
      return MealWithDessert(self.dessert, "Eaten-%s" % self.starter, main=self.main)

...对于更复杂的功能,这两个选项都非常可怕。肯定有更好的方法吗?

【问题讨论】:

标签: python inheritance methods overriding


【解决方案1】:

下面的sn-p实现了你想做的,希望对你有帮助

class Meal(object):
    def __init__(self, starter, main="steak"):
            self.starter = starter
            self.main = main

    def new_meal_same_starter(self, new_main):
        meal_class = globals()[self.__class__.__name__]
        new_args = self.__dict__.copy()
        new_args['starter'] = "Eaten-%s" % new_args['starter']
        new_args['main'] = new_main
        return meal_class(**new_args)

    def __repr__(self):
        return "%s %s" % (self.starter, self.main)



class MealWithDessert(Meal):
    def __init__(self, dessert, *args, **kwargs):
            super(MealWithDessert, self).__init__(*args, **kwargs)
            self.dessert = dessert

    def __repr__(self):
        return "%s %s %s" % (self.starter, self.main, self.dessert)


x = MealWithDessert("cake", "salad", "pizza")
print(x)
y = x.new_meal_same_starter("tofu")

a = Meal("Rice")
b = a.new_meal_same_starter("Bread")

print(a)
print(b)

print(y)

print(x)

【讨论】:

  • 嗨@samuel,它适用于覆盖函数只是替换一些数据的琐碎情况,但我对覆盖函数正在做更复杂的事情的更普遍的问题感兴趣。我已经更新了示例以使其更清晰。
  • 你好@RobertCarver 虽然我无法想象你的实现有多复杂,但我认为我所做的更新涵盖了问题中的迫切需要。我也更新了答案
  • 嗨@Samuel,虽然不是很漂亮,但它确实有效,至少这意味着继承的类使用是干净的。看看我能不能用装饰器包裹起来。
  • @RobertCarver 很高兴知道它会有所帮助,至少对于您的迫切需要。感谢您的反馈
【解决方案2】:

我认为这里的问题是课堂用餐中的以下方法

   def new_meal_same_starter(self, new_main):
       return Meal(self.starter, main=new_main)

你只需要用 new_main 更新主菜。所以试试这个:

   def new_meal_same_starter(self, new_main):
       self.main=new_main

如果需要从方法中返回,则覆盖它:

   def new_meal_same_starter(self, new_main):
      return MealWithDessert(self.dessert, self.starter, main=new_main)

【讨论】:

  • 这会修改同一个对象而不是返回一个新对象,这可能不是 OP 想要的(因此方法名称中的 new
  • 嗨@Vijay显然这是一个更复杂的真实示例的微不足道的代码。在实践中,new_meal_same_starter 方法可以做一些比仅仅替换一些数据更复杂的事情。抱歉,如果问题中没有明确说明。
  • 嗨@RobertCarver 问题仍然不清楚。 1.你想返回新的实例对象还是现有的? 2. 你说的复杂操作是作用于当前实例对象还是新实例对象?
  • 返回一个新实例。 basr 类中的 complex 方法作用于当前实例并返回基类的新实例。
猜你喜欢
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多