简体   繁体   中英

Can I change the default __add__ method in Python?

Is it possible to change the default __add__ method to do something else than just add?

For example, if the goal is with this line: 5+5 get The answer is 10 or anything else like 0 by changing __add__ to be xy instead of x+y ?

I know I can change __add__ in my own 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)

Can I somehow target the default __add__ method to change its behaviour? I intuitively think that __add__ is defined in each default data type to return specific results, but then again, the __add__ method is what we address when changing it for a specific class, so, is it possible to change the main __add__ logic?

Something along these lines?

class __add__():
    ...

Yes, you can overload whatever in user defined 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)

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)

Will not work for built-in types, eg resulting in TypeError: can't set attributes of built-in/extension type 'set'

Also please note that your implementation of __add__ modifies the original instance, which I don't like.. (just my note)

If you are looking for information about how the C level built-ins are defined you would want to look at some of the source code , note that I'm linking specifically to floats but the structure exists for all number types:

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

this is the structure for all the C function pointers that implement number methods, (for floats in this case) each builtin type that defines any number related methods will define a PyNumberMethods structure, this is then used in the formal definition of the type:

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

the PyTypeObject represents all the relevant information needed to construct the float object in python, (or equivalently, int or str etc.) containing all the methods, attributes, and necessary meta-data to work as a python type. So if you really wanted to change adding floats to instead do another well defined task you'd just change it to point to the other function:

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

If you wanted to write your own behaviour you could write your own function and point to it in this structure instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM