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 时会发生什么。
编辑:我在输入 c1
和 c2
的代码示例时犯了一个错误。现在修好了。我不是在实例化点,我是在实例化汽车。
您应该使用 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
个对象。
我很好奇你的Point
class,你能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
)更有意义。
这是基于 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 时会发生什么。
编辑:我在输入 c1
和 c2
的代码示例时犯了一个错误。现在修好了。我不是在实例化点,我是在实例化汽车。
您应该使用 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
个对象。
我很好奇你的Point
class,你能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 ofPoint
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
)更有意义。