4

将几个相同的方法添加到多个类中最 Pythonic 的方法是什么?


我可以使用类装饰器,但这似乎带来了相当多的复杂性,并且比其他方法更难编写和阅读。

我可以创建一个包含所有方法的基类,并让其他类继承,但是对于某些类,我很想允许多重继承,我经常阅读的是要避免或最小化。此外,“is-a”关系不适用。

我还可以将它们从方法更改为使它们成为独立函数,这些函数只期望它们的值通过鸭子类型提供适当的属性。这在某些方面是干净的,但它不是面向对象的,并且在何时可以在该类型的对象上使用函数时不太清楚。

我可以使用委托,但这要求所有想要调用的类都有调用辅助类方法的方法。这将使代码库比其他选项长得多,并且每次我想向助手类添加新函数时都需要添加一个委托方法。

我知道在某些情况下,将另一个类的实例作为属性很好地工作,但它并不总是干净地工作,并且会使调用变得比其他情况更复杂。

在玩了一会儿之后,即使它导致多重继承,我也倾向于继承。但是我犹豫了,因为大量的文本非常强烈地警告不要允许多重继承,并且一些(例如维基百科条目)甚至说继承只是为了代码重用,例如应该最小化。


举个例子可能会更清楚,所以对于一个简化的例子来说,我们正在处理许多不同的类,这些类都在 x、y 网格上具有一个位置。有很多操作我们可能希望为具有 x、y 位置的所有事物创建方法,例如获取两个此类实体之间的距离、或者它们之间的相对方向、中点等的方法。

让所有此类类访问这些仅依赖于将 x 和 y 作为属性的方法的最 Pythonic 方式是什么?

4

2 回答 2

3

对于您的具体示例,我会尝试利用鸭式打字。编写简单的函数,接收假定具有的对象xy属性:

def distance(a, b):
    """ 
    Returns distance between `a` and `b`.
    `a` and `b` should have `x` and `y` attributes.
    """

    return math.sqrt((a.x-b.x)**2 + (a.y-b.y)**2)

非常简单。为了清楚地说明如何使用该功能,只需将其记录下来。

于 2012-10-19T21:41:32.900 回答
2

普通的旧函数最适合这个问题。例如,而不是这个......

class BaseGeoObject:

  def distanceFromZeroZero(self):
    return math.sqrt(self.x()**2 + self.y()**2)
  ...

...只有这样的功能:

def distanceFromZeroZero(point):
  return math.sqrt(point.x()**2 + point.y()**2)

这是一个很好的解决方案,因为它也很容易测试 - 不必为了执行特定功能而进行子类化。

于 2012-10-19T22:21:13.200 回答