2010-03-02 87 views
4

我试图创建一个类,允许我将相同类的对象相加或相乘,或者将数字参数添加到数字参数到每个类的成员python如何实现多态算术运算符?

所以我的类是坐标(I我知道那里有很棒的软件包可以做我想要的所有东西,比我想象的更好,但现在我只是好奇而已)。

class GpsPoint(object): 
    """A class for representing gps coordinates""" 
    def __init__(self, x, y, z): 
     self.x = x 
     self.y = y 
     self.z = z 
    def __add__(self, other): 
     return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) 
    def __radd__(self, other): 
     return GpsPoint(self.x + other, self.y + other, self.z + other) 
    def __str__(self): 
     return "%d, %d, %d" % (self.x, self.y, self.z) 

这是我最初的尝试。我发现它的工作,但只有当我用一个数字参数第一

>>foo = GpsPoint(1,2,3) 
>>print 5 + foo 
6, 7, 8 
>>print foo + 5 
AttributeError: 'int' object has no attribute 'x' 

那么,什么是Python的方式来做到这一点,是有一个Python的方式,这只是愚蠢?我看到使用isinstance()的哲学问题是什么,我知道我可以折腾在tryexcept块我只是好奇我怎么应该去做这件事。

回答

6

“Pythonic”的方式是“请求原谅而不是权限” - 也就是说,不要事先检查类型,而是尝试添加,如果失败,则捕获异常并处理它,如下所示:

class GpsPoint(object): 
    """A class for representing gps coordinates""" 
    def __init__(self, x, y, z): 
     self.x = x 
     self.y = y 
     self.z = z 
    def __add__(self, other): 
     try: 
      return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) 
     except AttributeError: 
      return GpsPoint(self.x + other, self.y + other, self.z + other) 
    def __radd__(self, other): 
     try: 
      return GpsPoint(self.x + other.x, self.y + other.y, self.z + other.z) 
     except AttributeError: 
      return GpsPoint(self.x + other, self.y + other, self.z + other) 
    def __str__(self): 
     return "%d, %d, %d" % (self.x, self.y, self.z) 
+0

要求宽恕是碰到虚假同源问题的好方法,但在重载数字运算符的情况下,很清楚x,y和z是什么意思。如果你添加了一个完全不相关的四维(w,x,y,z)数字类的实例,那么你只有一个问题:那么你会默默地失去w。 – markpasc 2010-03-03 00:04:53

+0

太棒了,谢谢。这就是我最终做的事情('__radd__ = __add__')。我*感觉*喜欢它有点冒险,但它适合我的目的很好,并且似乎很受欢迎作为答案。 – Tyler 2010-03-03 08:27:24

+1

如果您的区块返回 'self + GpsPoint(other,other,other)' 这似乎更像是将数字映射到GpsPoints的想法,您希望将它们更改为GpsPoints,然后添加它们。 – 2010-03-03 18:30:26

2

您将不得不尝试确定other是什么类型,至少在与GpsPoint兼容的范围内。如果你无法弄清楚,那么只需返回NotImplemented,解释器会尝试从那里处理它。

0

简短回答:使用isinstance()。

在您的方法中没有其他方法可以对“其他”类型进行剥削。另外,如果你检查了很多python库的源代码,你会发现有很多地方使用了isinstance()。所以这只是python中的艺术状态:-)。