【问题标题】:overiding class attributes but not methods in the child class覆盖类属性但不覆盖子类中的方法
【发布时间】:2020-05-31 14:53:28
【问题描述】:

我有这个问题,例如我定义了一个Vehicle 类。

class Vehicle():
    speed = 0
    def __init__(self):
        pass
    def get_speed(self):
        return Vehicle.speed

我有一个类属性 speed,我将在 Bike 子类中覆盖它

class Bike(Vehicle):
   speed = 20

如果我实例化一个 Bike 类型的新对象,我会得到这个

>>> a = Bike()
>>> a.get_speed()
0

如何让它在不必重写父类方法的情况下获得。

>>> a.get_speed()
20

我确实有一个解决方案,但我不知道这是否是一个好的编程习惯,因为实例变量应该是该实例唯一的,所以现在我很困惑。

class Vehicle():
   def __init__(self):
      self.speed = 0

   def get_speed(self):
      return self.speed

class Bike(Vehicle):
   def __init__(self):
      self.speed = 20

我是否应该将它重新声明为实例变量,这样如果我在构造函数中覆盖self.speed = 20,那么我会得到

>>> a = Bike()
>>> a.get_speed()
20

任何帮助将不胜感激,在此先感谢。

【问题讨论】:

  • 取决于一点。在您的设计中,同一级别的所有车辆是否都具有相同的速度,或者可以假设两辆自行车的速度不同?
  • 所有自行车都有相同的速度,我将创建另一个子类,例如汽车,所有汽车的速度可能相同,例如 30,顺便感谢您这么快的评论。
  • 在这种情况下,只需将return Vehicle.speed 更改为return self.speed 即可。

标签: python class oop inheritance


【解决方案1】:

如果在对象的__dict__ 中找不到属性,即当它不是实例属性时,Python 将在接下来的类中查找该属性。

这就是为什么你可以这样做:

>>> class Vehicle:
...     speed = 0
...     def get_speed(self):
...         return self.speed
...     
>>> class Bike(Vehicle):
...     speed = 20
...     
>>> a = Bike()
>>> a.get_speed()
20

此外,我会摆脱 get_speed 方法。编写 getter 和 setter 不是惯用的 Python。只需使用a.speed

如果您想保护属性不被设置,请考虑使用properties

【讨论】:

  • 非常感谢timgeb,我去重构我的代码。
【解决方案2】:

如果您需要 get_speed 成为类范围的属性(而不是实例范围的),您可以使用 @classmethod 装饰器:

class Vehicle():
    speed = 0
    def __init__(self):
        pass

    @classmethod
    def get_speed(cls):
        return cls.speed

尽管如此,仍然可以在类实例中覆盖 speed 属性。

【讨论】:

  • 非常感谢 Pavel 这么快的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
  • 2011-08-19
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
相关资源
最近更新 更多