【问题标题】:is it possible to call a method from another subclass in Python?是否可以从 Python 中的另一个子类调用方法?
【发布时间】:2020-12-09 19:40:20
【问题描述】:

我正在尝试构建机器人行为的模拟。我有一个 Robot 父抽象类和一个正常工作的 NormalRobot 子类。我想构建一个 FaultyRobot 子类,可能带有部分“并行”继承之类的东西?

父类 Robot 有一个抽象的 move() 方法,因为我希望我的所有 Robot 子类都能够以相同的名称调用 move()

NormalRobot 有一个功能方法move(),它模拟一个“转”,在指定方向上移动指定距离。 (多次调用move()模拟多个“转”)

FaultyRobot 还应该有一个move() 方法,它几乎与 NormalRobot 的 move() 相同,只是在“转弯”开始时它随机有可能不移动和改变方向。显然,我可以通过编写随机代码(我在辅助方法 turn_is_faulty() 中拥有)并复制粘贴 NormalRobot 的 move() 的内容来做到这一点。但显然,重复代码是一种不好的礼仪。 Python 继承使得从父类 Robot 继承 move() 方法变得非常容易,但我需要来自并行子类 NormalRobot 的 move()

我想象代码看起来像

def Class FaultyRobot:
    def move(self):
        if self.turn_is_faulty():
            self.set_robot_direction(360 * random.random())
        else:
            #call the NormalRobot move() 


Python 是否允许某种部分“并行”继承?

【问题讨论】:

  • 如果故障类继承自普通类而不是ABC,它可以调用super方法。不过,这有点尴尬。您还可以使用 ABC 的外部/静态方法来处理正确的移动(而不是在普通类中定义),然后让普通类直接使用该单独的函数,并让故障类有条件地使用它。跨度>
  • 您认为Robot 的哪些子类不会 使用NormalRobot.move 或其变体?听起来更像FaultyRobot 应该继承自NormalRobot。另一种选择是让Robot.move 提供默认实现,以便FaultyRobot 可以通过super 访问它。
  • 另一种观点是,一个正常的机器人和一个故障机器人是一样的,只是它出现故障的概率是0。
  • @chepner 认为 NormalRobot 出现错误动作的概率为 0,这是一个绝妙的观点!谢谢你。然而,NormalRobot 和 FaultyRobot 对其功能的其他部分有其他方法,这使得它们无法完全相互继承
  • @Carcigenicate 我希望 ABC move() 部分是抽象的,以便我可以编写具有不同移动算法的其他子类,然后我可以比较不同子类的效率对彼此。这里特别是 FaultyRobot 的 move() 与 NormalRobot 的 move() 几乎相同,但其他子类的 move() 方法可能具有完全不同的内容

标签: python inheritance subclass


【解决方案1】:

我会说“故障机器人”只是一个“正常机器人”,故障很少。

import numpy as np

class NormalRobot():
  def __init__(self, x):
    self.x = x
  def move(self, d):
    self.x += d

  def __repr__(self):
    return f"Position: {self.x}"
  
class FaultyRobot(NormalRobot):
  def __init__(self, x, is_faulty=True):
    self.x = x
    self.is_faulty = is_faulty

  def turn_is_faulty(self):
    return self.is_faulty

  def move(self, d):
    if self.turn_is_faulty():
      self.x += np.random.random()
    else:
      super().move(d)

测试:

n = NormalRobot(0)
f = FaultyRobot(0)
nf = FaultyRobot(0, False)

n.move(10)
nf.move(10)
f.move(10)

print (n, nf, f)

输出:

Position: 10 Position: 10 Position: 0.07103605819788694

【讨论】:

    【解决方案2】:

    您可以将共享功能放入 mixin 类中。

    import random                                 
                                         
    class AbstractRobot:
        """My 1 dimensional robot"""
        def __init__(self, start_at):
            self.pos = start_at
        
    class RobotMoveMixin:
    
        def move(self, delta):
            self.pos += delta
            print('moved to', self.pos)
    
    class GoodRobot(RobotMoveMixin, AbstractRobot):
        pass
        
    class BadRobot(RobotMoveMixin, AbstractRobot):
    
        def move(self, delta):
            print("bad robot")
            if random.choice((True, False)):
                super().move(delta)
    
    robot = BadRobot(0)
    for _ in range(10):
        robot.move(3)
    

    现在 GoodRobot 及其继承者获得了良好的运动,而 BadRobot 及其继承者获得了混乱的运动。

    【讨论】:

      【解决方案3】:

      感谢大家的帮助。我最终找到了另一个我认为可能很有趣的解决方案,所以我发布了它。我的解决方案没有在任何形式上使用继承,所以我怀疑你们中的一些人可能有类似的东西但没有发布它,因为它似乎与我的问题的措辞相去甚远。这是我自己的问题,因为我认为这是继承的问题,所以我认为可以通过更好的继承结构找到解决方案。幸好有一个简单的解决方法。

      def Class FaultyRobot:
          def move(self):
              if self.turn_is_faulty():
                  self.set_robot_direction(360 * random.random())
              else:
                  StandardRobot.move(self)
      

      Python 确实允许在定义新子类的move() 时调用一个子类的move()

      【讨论】:

        猜你喜欢
        • 2016-06-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多