【问题标题】:__add__ two class objects__add__ 两个类对象
【发布时间】:2017-09-25 14:39:55
【问题描述】:

我一直在通过搜索教程来学习 Python 2。我正在发现关于 class 的事情。我在__add__ dunder-method 遇到了一些麻烦。我不知道如何添加 2 个类的对象。

为了更清楚:

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        for i in zip(*(self.num + other.num)):
            # and then some codes over here

#when:
obj1 = Add_obj(2, 5)
obj2 = Add_obj(4, 7)
# it should return Add_obj(6, 12)

我知道添加 2 个对象不是最好的方法?

【问题讨论】:

  • 你应该在还在学习的时候切换到 Python 3.6 - 这是对 v2.x 的改进 - pythonclock.org
  • 什么是self.num?一个序列还是一个数字?也许将文档字符串添加到 __init__ 或类本身。首先:也许只需在 for 循环中打印 i 以查看您拥有的内容 - 然后尝试弄清楚如何处理它。
  • 您的尝试和两个答案都需要注意的一点:当两个对象的num 长度不同时,使用zip 将截断更长的num。因此,添加不同大小的对象会起作用,但这不太可能是预期的行为。您可能想要添加一个明确的完整性检查,以确保两个对象具有相同的长度,或者使用根据需要填充 0 的解决方案来填充较短的对象。
  • 第二个在 Python 3 上学习的建议。如果你有一个非常具体的原因,学习遗留的 Python 才是你应该做的事情。与 2.7 相比,3.6 中的出色功能列表非常长 - 无论如何您都会更喜欢使用它。

标签: python class python-2.x


【解决方案1】:

您可以在operator.add 中使用map__add__ 中的可迭代解包(使用*)。例如:

import operator

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        return self.__class__(*map(operator.add, self.num, other.num))

它确实返回了“预期对象”:

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7)
>>> obj1 + obj2
Add_obj(6, 12)

但是map 并不是真正需要的,它只是一种非常高效且简短的方法来实现这一点。您也可以使用理解和 zip 代替:

def __add__(self, other):
    return self.__class__(*[num1+num2 for num1, num2 in zip(self.num, other.num)])

正如 cmets 中所指出的,这也可以工作,但当两个 Add_obj 的长度不同时,可能会产生意想不到的(甚至是错误的)结果。如果你想禁止添加两个不同大小的对象,你可以引发一个异常:

def __add__(self, other):
    if len(self.num) != len(other.num):
        raise ValueError('cannot two Add_obj with different lengths')
    ...  # use one of the both approaches from above

例如:

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7, 2)
>>> obj1 + obj2
ValueError: cannot two Add_obj with different lengths

或者你可以零填充较短的:

from itertools import izip_longest as zip_longest  # only zip_longest on Python 3

class Add_obj:

    ...

    def __add__(self, other):
        return self.__class__(*[num1+num2 for num1, num2 in zip_longest(self.num, other.num, fillvalue=0)])

例如:

>>> obj1 = Add_obj(2, 5)
>>> obj2 = Add_obj(4, 7, 2)
>>> obj1 + obj2
Add_obj(6, 12, 2)

【讨论】:

  • 您也可以使用lambda x, y: x + y insead of operator.add 并保存一个导入。
  • 我选择了mapoperator.add,因为它很快。使用您的 lambda 会破坏性能目的。
【解决方案2】:

使用zip 是个好主意。

class Add_obj:
    def __init__(self, *num):
        self.num = num

    def __repr__(self):
        return 'Add_obj{}'.format(self.num)

    def __add__(self, other):
        return Add_obj(*(sum(pair) for pair in zip(self.num, other.num)))


obj1 = Add_obj(2, 5)
obj2 = Add_obj(4, 7)
obj3 = obj1 + obj2

print(obj1)
print(obj2)
print(obj3)

【讨论】:

  • 本来打算向另一个答案建议确切的语法sum(pair) for pair in ...,我想我也会+1。
猜你喜欢
  • 1970-01-01
  • 2013-05-20
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多