如何重写魔术方法?

3 投票
3 回答
2847 浏览
提问于 2025-04-17 20:55

今天,我在看一本关于Python的书,了解到有一些神奇的方法,比如__add____mul__

不过,书里没有解释这些方法怎么用。

于是,我试着自己搞明白,但我不知道怎么重写这些神奇的方法。以下是我尝试的代码。

>>> class Num(int):
...     def __init__(self, number):
...             self.number = number
...     def __add__(self, other):
...             self.number += other*100
...             return self.number
... 
>>> num = Num(10)
>>> num.number + 10
20

有没有人能帮我理解这些神奇的方法是怎么工作的?

3 个回答

1

你想要重写的是你自己这个的方法,而不是某个特定属性的方法。

在你的实现中,num.number + 10 其实不会调用你这个__add__ 方法,而是会调用你正在操作的那个变量的方法——在这个例子里,就是一个 int(整数)。

num.number.__add__

所以你看到的输出是 20——它使用的是默认的 __add__ 方法,10 + 10 = 20。

如果你想使用你自己的方法,你可以这样做:

num = Num(10)
num + 10

这样你就调用了你的 num.__add__ 方法。

3
In [12]: class Num(int):
    ...:      def __init__(self, number):
    ...:              self.number = number
    ...:      def __add__(self, other):
    ...:              #self.number += other*100 #why do you want to do other*100?
    ...:              return Num(self.number+
    ...:                         Num(other).number) #wrap "other" with "Num"
                                                    #in case "other" is an "int"

In [13]: num = Num(10)
    ...: print num+10
20

其实,如果你的 Numint 的子类,你并不需要重写 __add__ 方法。只要在 __init__ 方法里调用 super 就可以了:

In [19]: class Num(int):
    ...:     def __init__(self, *args):
    ...:          super(Num, self).__init__(args)

In [20]: Num(10)
Out[20]: 10

In [21]: Num(10)+10
Out[21]: 20

这样的话,就不需要其他属性,比如 self.number 了。

3
class Num:
    def __init__(self, number):
        self.number = number
    def __add__(self, other):
        self.number += other*100

>> num = Num(10)
>> num.number
10
>> num + 10  # note that you are adding to num, not to num.number
>> num.number
1010

这就是重写 __add__ 的工作原理。带有 return 的版本:

class Num:
    def __init__(self, number):
        self.number = number
    def __add__(self, other):
        return self.number + other*100

>> num = Num(10)
>> num.number
10
>> num + 10  # again adding to num
1010
>> num.number
10

所以基本上,当 Python 看到

x + y
x += y
x * y
x *= y
etc

它会把它转换成

x.__add__(y)
x.__iadd__(y)
x.__mul__(y)
x.__imul__(y)
etc

撰写回答