重载 + 以支持元组

6 投票
7 回答
3206 浏览
提问于 2025-04-16 16:30

我想在Python中写一些像这样的代码:

a = (1, 2)
b = (3, 4)
c = a + b # c would be (4, 6)
d = 3 * b # d would be (9, 12)

我知道可以重载运算符来处理自定义类,但有没有办法重载运算符来处理成对的数据呢?

当然,像这样的解决方案

c = tuple([x+y for x, y in zip(a, b)])

是可以工作的,但如果不考虑性能,它们看起来没有重载 + 运算符那么好看。

当然,你可以定义 addmul 这样的函数:

def add((x1, y1), (x2, y2)):
    return (x1 + x2, y1 + y2)

def mul(a, (x, y)):
    return (a * x, a * y)

但能够写 q * b + r 而不是 add(times(q, b), r) 会更好。

有什么想法吗?

补充说明:顺便提一下,我意识到因为 + 目前是用来连接元组的,所以重新定义它可能不太明智,即使这是可能的。这个问题对于 - 也是适用的,比如说 =)

7 个回答

2

用Python的复数来处理这个问题绝对是一个方法,虽然看起来不太美观。

a = 1 + 2j
b = 3 + 4j
c = a + b # c would be 4 + 6j
d = 3 * b # d would be 9 + 12j

这样就不需要再定义一个额外的类了。

另外,进一步补充之前的回答,

class T(tuple):
    def __add__((x, y), (x1, y1)):
        return T((x+x1, y+y1))
    def __rmul__((x, y), other):
        return T((other * x, other * y))

这样可以提高性能,不过会限制实现只能使用成对的数据。

3

你可以从 tuple 这个类继承,并且重写它的 __add__ 方法。下面是一个非常简单的例子:

class mytuple(tuple):
    def __add__(self, other):
        assert len(self) == len(other)
        return tuple([x + y for x, y in zip(self, other)])

mt = mytuple((5, 6))
print mt + (2, 3)  # prints (7, 9)

不过我不太推荐这种做法,因为元组本身并不是为了这个目的设计的。如果你想进行数字计算,直接使用 numpy 就好了。

7

和Ruby不同,在Python中你不能改变内置类型的行为。你能做的就是创建一个新的类型,这个新类型是从内置类型“派生”出来的。不过,直接写出来的字面量还是会生成内置类型。

你能做到的可能就是这样:

class T(tuple):
    def __add__(self, other):
        return T(x + y for x, y in zip(self, other))
    def __rmul__(self, other):
        return T(other * x for x in self)
a = T((1, 2))
b = T((3, 4))
c = a + b # c would be (4, 6)
d = 3 * b # d would be (9, 12)

撰写回答