我可以更改 Python 中的默认 __add__ 方法吗?

Can I change the default __add__ method in Python?

是否可以更改默认的 __add__ 方法来执行除添加之外的其他操作?

例如,如果目标是这一行: 5+5 通过将 __add__ 改为 x-y 而不是 x+y?

得到 The answer is 10 或类似 0 的任何东西

我知道我可以自己改变 __add__ classes:

class Vec():
    def __init__(self,x,y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f'{self.x, self.y}'

    def __add__(self, other):
        self.x += other.x
        self.y += other.y
        return Vec(self.x,self.y)

    
v1 = Vec(1,2)
v2 = Vec(5,3)

v1+v2
# (6, 5)

我能否以某种方式针对默认 __add__ 方法来更改其行为?我直觉上认为 __add__ 在每个默认数据类型中都定义为 return 特定结果,但话又说回来, __add__ 方法是我们在针对特定 class 更改它时要解决的问题], 那么,是否可以改变主要的 __add__ 逻辑?

类似的东西?

class __add__():
    ...

是的,您可以重载用户定义的任何内容 类。

class Vec():
    def __init__(self,x,y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f'{self.x, self.y}'

    def __add__(self, other):
        self.x += other.x
        self.y += other.y
        return Vec(self.x,self.y)

    
v1 = Vec(1,2)
v2 = Vec(5,3)

print(v1+v2)

# using lambda function
Vec.__add__ = lambda self,other: Vec(self.x-other.x,self.y-other.y)
print(v1+v2)

# using "normal" function
def add(self,other):
    self.x -= other.x
    self.y -= other.y
    return Vec(self.x,self.y)
Vec.__add__ = add
print(v1+v2)

不适用于 built-in 类型,例如导致 TypeError: can't set attributes of built-in/extension type 'set'

另请注意,您对 __add__ 的实现修改了原始实例,我不喜欢这样......(只是我的注释)

如果您正在寻找有关如何定义 C 级 built-ins 的信息,您可能希望查看 some of the source code,请注意,我专门链接到浮点数,但结构存在于所有号码类型:

static PyNumberMethods float_as_number = {
    float_add,          /* nb_add */
    float_sub,          /* nb_subtract */
    float_mul,          /* nb_multiply */

这是所有实现数字方法的C函数指针的结构,(在这种情况下对于浮点数)定义任何数字相关方法的每个内置类型都将定义一个PyNumberMethods结构,然后使用在正式的 definition of the type:

PyTypeObject PyFloat_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "float",
    sizeof(PyFloatObject),
   
    ...
        
    &float_as_number,                           /* tp_as_number */

PyTypeObject 表示在 python 中构造 float 对象所需的所有相关信息(或等效地, intstr 等。 ) 包含所有方法、属性和必要的 meta-data 以作为 python 类型工作。所以如果你真的想改变添加浮点数而不是做另一个定义明确的任务,你只需将它更改为指向另一个函数:

static PyNumberMethods float_as_number = {
    float_sub,          /* nb_add.  overrides to do subtraction because I want to break everything >:D */
    float_sub,          /* nb_subtract */

如果您想编写自己的行为,您可以编写自己的函数并在该结构中指向它。