This question already has answers here:
Overriding special methods on an instance
                                
                                    (5个答案)
                                
                        
                                3年前关闭。
            
                    
考虑以下代码:

class Foo:
    def __mul__(self,other):
        return other/0
x = Foo()
x.__mul__ = lambda other:other*0.5
print(x.__mul__(5))
print(x*5)


在Python2(带有from future import print)中,此输出

2.5
2.5


在Python3中,此输出

2.5

---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-1-36322c94fe3a> in <module>()
      5 x.__mul__ = lambda other:other*0.5
      6 print(x.__mul__(5))
----> 7 print(x*5)

<ipython-input-1-36322c94fe3a> in __mul__(self, other)
      1 class Foo:
      2     def __mul__(self,other):
----> 3         return other/0
      4 x = Foo()
      5 x.__mul__ = lambda other:other*0.5

ZeroDivisionError: division by zero


当我尝试实现支持代数运算子集的类型时,我遇到了这种情况。对于一个实例,我需要修改乘法函数以保持懒惰:必须推迟一些计算,直到实例与另一个变量相乘。猴子补丁程序在Python 2中有效,但我注意到它在3中失败了。

为什么会这样?
有没有办法在Python3中获得更灵活的运算符重载?

最佳答案

那不是猴子补丁。

这将是一个猴子补丁:

class Foo:
    def __mul__(self, other):
        return other / 0

Foo.__mul__ = lambda self,other: other * 0.5

x = Foo()
x*9    # prints 4.5


x.__mul__ = lambda other:other*0.5所做的工作是在__mul__实例上创建x属性。

然后,预计x*5将调用x.__mul__(5)。而且确实如此,在Python 2中。

在Python 3中,它称为Foo.__mul__(x, 5),因此未使用该属性。

Python 2的功能与Python 3相同,但这不是因为Foo是作为旧类创建的。

这段代码对于Python 2和Python 3是等效的:

class Foo(object):
    def __mul__(self,other):
        return other/0
x = Foo()
x.__mul__ = lambda other:other*0.5
print(x.__mul__(5))
print(x*5)


这将引发一个例外。注意(object)

关于python - 猴子修补运算符重载在Python2和Python3中的行为不同,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39801885/

10-12 18:37