请考虑以下代码:
var toObj = (ks, vs) => ks.reduce((o,k,i)=> {o[k] = vs[i]; return o;}, {});
var keys=['one', 'two', 'three'],
values = [1, 2, 3];
var obj = toObj(keys, values);
console.log(obj);
在Python2中(带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)
),输出
from future import print
在Python3中,输出
2.5
2.5
当我尝试实现支持代数运算子集的类型时,我遇到了这种情况。例如,我需要修改laziness的乘法函数:必须推迟一些计算,直到实例与另一个变量相乘。猴子补丁在Python 2中工作,但我注意到它在3中失败了。
为什么会这样? 有没有办法在Python3中获得更灵活的运算符重载?
答案 0 :(得分:2)
这不是一个monkeypatch。
这可能是一个monkeypatch:
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)
。
答案 1 :(得分:1)
您无法覆盖实例级别的特殊方法。基于python' documentation:
对于自定义类,只有在对象类型上定义的特殊方法的隐式调用才能保证正常工作,而不是在对象的实例字典中。
这种行为背后的基本原理在于许多特殊方法,例如
__hash__()
和__repr__()
,它们由所有对象实现,包括类型对象。如果这些方法的隐式查找使用了传统的查找过程,那么在类型对象本身上调用它们时会失败:
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
因此,一种简单的方法是为您的猴子修补目标定义一个常规函数,并为其指定新方法:
In [45]: class Foo:
def __init__(self, arg):
self.arg = arg
def __mul__(self,other):
return other * self.arg
def _mul(self, other):
return other/0
演示:
In [47]: x = Foo(10)
In [48]: x * 3
Out[48]: 30
In [49]: my_func = lambda x: x * 0.5
In [50]: x._mul = my
my_func mypub/
In [50]: x._mul = my_func
In [51]: x._mul(4)
Out[51]: 2.0