理解Python中的算术运算符

2 投票
5 回答
532 浏览
提问于 2025-04-18 11:11

我目前的理解是,像 '+' 和 '-' 这样的算术运算符其实是一种特殊的方法,属于整数类。它们看起来有点不同,因为你不需要像这样写算术操作:x.__add__(y),但实际上,当你写 x + y 时,背后就是在执行这个操作。

我第一个问题是:我这样理解对吗?

我的第二个问题是:在 __add__ 方法中发生了什么?我在任何文档中都找不到相关信息。我想理解这个过程是如何避免无限回归的,因为我只能想象这个方法像这样:

def __add__(a,b):
   return a + b

但当然,你并没有解释 '+' 是怎么回事,这就导致了无限回归。

我希望我的问题清楚,因为我脑海中有点模糊。基本上,我想对 Python 的基础知识有一个好的理解。(也许其他语言也是?)

5 个回答

0

你说得对:

class Test(object):

    def __add__(self, other):
        return self + other

这样会引发问题:

>>> a = Test()
>>> b = Test()
>>> a + b

Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    a + b
  File "<pyshell#27>", line 4, in __add__
    return self + other
  ...
  File "<pyshell#27>", line 4, in __add__
    return self + other
RuntimeError: maximum recursion depth exceeded

不过,类的加法并不是这样实现的。通常,你会把实例的加法定义为对属性的加法,比如:

class Money(object):

    def __init__(self, amount):
        self.amount = amount

    def __add__(self, other):
        return Money(self.amount + other.amount)

__add__ 方法中对 amount 属性的加法,具体取决于 amount 的类型是怎么实现 __add__ 的,但因为:

>>> 1 + 2
3

这样工作,所以你可以假设这不是“乌龟”一直到底的情况!

0

其实,+这个符号是一个运算符,它是任何编程语言的基本组成部分。Python和大多数其他面向对象的编程语言允许你为自定义的类定义+运算符。这是通过在你新创建的类里定义__add__方法来实现的。

希望这能帮助你更好地理解。

1

对于数字类型来说,__add__这个方法很可能是用底层的原生代码实现的,所以出现无限递归的情况几乎不可能。因此,你写的返回值a+b实际上是调用了底层的原生代码。

2

关于 __add__(a, b) 这个数字相加的功能:

我不是Python专家,但我猜这个操作会调用一些底层的代码来实际进行计算。这个底层代码是用你正在使用的Python版本所写的语言实现的。例如,如果你使用的是CPython,那么它会调用一个用C语言写的(已经编译好的)函数来完成这个操作。

4

确实,Python会把+-这两个操作符转换成.__add__()的调用,但它也会在第二个操作数上使用__radd__()方法来处理反向操作。这让自定义类型在和标准类型一起使用时,可以插入自己的逻辑。

当你执行x + y时,发生的事情是:

  • 如果yx的子类,首先会尝试y.__radd__(x);这样可以让你用更具体的类来覆盖默认行为。
  • 接着尝试x.__add__(y),如果成功了,那就是这个表达式的结果。如果这个调用返回了特殊的NotImplemented,就继续到下一步。
  • 再尝试y.__radd__(x);如果成功了,那就是这个表达式的结果。如果它也返回NotImplemented,那么就会抛出一个TypeError异常,表示操作失败。

因为Python内置类型是用C语言实现的,所以__add__的实际实现不会引发竞争条件。int.__add__的C代码处理的是C整数值和C语言的+操作符,实际上就是把数字加在一起。

在自定义的Python对象中,通常是通过对属性或其他值进行相加来表达加法:

def __add__(self, other):
    if not isinstance(other, type(self)):
        return NotImplemented  # cannot handle other types
    return type(self)(self.foobar + other.foobar + self.summation_margin)

这些属性可能有自己的__add__实现。

撰写回答