Python子类丢失子类属性

Python subclass loses subclass attributes

这是基于 shapely package 的问题,但我认为这是一个更笼统的问题。

基本上我有两个 类 来自 shapely。一个叫做Point,另一个叫做MultiPoint。您用坐标元组实例化 Point,用 Point 列表实例化 MultiPoint。您可以使用索引访问多点中的点。

 p1 = Point((1,1))
 p2 = Point((2,2))
 mp = MultiPoint([p1,p2])

 In [315]: MultiPoint((p1, p2))[0]
 Out[315]: <shapely.geometry.point.Point at 0x1049b1f50>

我想继承 Point 并将其用于汽车的位置。

class Car(Point):
    def __init__(self, coords, speed):
        super(self.__class__, self).__init__(coords)
        self.speed = speed

现在我可以写了

 c1 = Car((1,1), speed=2)
 c2 = Car((2,2), speed=3)
 mc = MultiPoint([c1,c2])

我可以使用索引访问汽车,但它们不再是汽车。他们是点。特别是他们没有属性速度。

In [316]: MultiPoint((c1, c2))[0]
Out[316]: <shapely.geometry.point.Point at 0x1049b1610>

In [317]: MultiPoint((c1, c2))[0].speed
AttributeError: 'Point' object has no attribute 'speed'

有没有办法通过继承 Multipoint 来解决这个问题?我想我不知道当汽车(点)传递给 MultiPoint 时会发生什么。

编辑:我在输入 c1c2 的代码示例时犯了一个错误。现在修好了。我不是在实例化点,我是在实例化汽车。

您应该使用 Car class 构造函数实例化 Car 对象:

 c1 = Car((1,1), speed=2)
 c2 = Car((2,2), speed=3)
 mc = MultiPoint([c1,c2])

Python 遵循鸭子打字原则:

If it quacks like a duck and looks like a duck, then it must be a duck.

这使得多态性变得非常容易。您的对象 不是任何特定的 class,它们 的行为 取决于它们的上层class。此行为在不同情况下可能会有所不同。

您的 MultiPoint class 很乐意接受 Car 个对象来代替 Point 个对象。

我很好奇你的Pointclass,你能post吗?

问题在这里:

 c1 = Point((1,1), speed=2)
 c2 = Point((2,2), speed=3)
 mc = MultiPoint([c1,c2])

根据描述,您必须实例化 Car 对象,而不是 Points:

c1 = Car((1,1), 2)
c2 = Car((2,2), 3)

虽然 MultiPoint class 在概念上是 Point 的集合,但它实际上并没有保留对 Point 实例(或 Point subclass) 传递给它的构造函数。相反,它将坐标从点复制到它自己的内部数据结构中。这会丢失您添加到 Car subclass 的额外属性。这是 the docs 中的简短段落:

The constructor also accepts another MultiPoint instance or an unordered sequence of Point instances, thereby making copies.

我建议将您的 Car class 设计为具有 Point 属性(或者可能是对 MultiPoint 和索引的引用),而不是使其成为 Point 的子 class。当您可以改用封装时,从另一个概念上不相关的类型继承通常不是一个好主意。

记住继承意味着 "IS-A",而封装意味着 "HAS-A",这有助于理清你的设计。例如,一个矩形 IS-A 形状,所以如果你写一个 Shape class,一个 Rectangle 将是一个完全合理的子 class。在您的情况下,您的继承表明 Car IS-A Point,这没有多大意义。说 Car HAS-A position(即 Point)更有意义。