Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to overload operators for native datatypes?

Tags:

For example, if I try to do:

a_string + an_int

... where a_string is type 'str' and an_int is type 'int', or:

an_int + a_string

There would be a TypeError because there is no implicit conversion of the types. I understand that if I were using my own subclasses of int and string, I would be able to overload the __add__() method in my classes to achieve this.

However, out of curiosity, I would like to know: would it be possible to overload the + operator in the class definitions of int and str, so that __add__(int,str) and __add__(str,int) automatically concatenate them as strings?

If not, what are the reasons why a programmer should not overload the operators for a native datatype?

like image 232
Anton Avatar asked Aug 08 '16 14:08

Anton


2 Answers

In general, without reverting to the C-level API, you cannot modify attributes of builtin types (see here). You can, however, subclass builtin types and do what you want on the new types. For the question you specifically asked (making the addition string based), you'd modify __add__ and __radd__:

class Int(int):
    def __add__(self, other):
        return Int(int(str(self) + str(other)))

    def __radd__(self, other):
        return Int(str(other) + str(self))

>>> Int(5) + 3
53

>>> 3 + Int(5) + 87
3587
like image 92
Ami Tavory Avatar answered Sep 26 '22 17:09

Ami Tavory


As pointed out above, you can't (unless you are up to building your own Python implementation). That is, you cannot change the way '1'+1 is handled if encountered in code. But you can mess with builtin functions however you please:

>>> int = str
>>> type(1)
<class 'int'>
>>> type('1')
<class 'str'>
>>> int(1)
'1'
>>> type(int(1))
<class 'str'>

It's little more than an enlightening example of first-class functions' awesomeness, thoug. Any changes you make stay in a namespace you are making them in. Consider this:

>>> str=int
>>> str('1')
1
>>> str('asd')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'asd'
>>> input()
2
'2'
>>> 

You are using whatever you put in str, in this case int. But input() knows better and falls back to the builtins. There may be some weird trick with closures that'll make it refer to your implementation, but I can't find it. By the way, original str is in __builtins__.str, should you need it back.

Pulling the same trick on builtin's methods doesn't work:

>>> int.__add__ = str.__add__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'
like image 40
Synedraacus Avatar answered Sep 25 '22 17:09

Synedraacus