Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using reverse operators in Python

I have never handled reverse operators before, so please no flaming! Just finished learning about them so wanted to try them out. But for some reason, it is not working. Here is the code:

>>> class Subtract(object):
    def __init__(self, number):
        self.number = number
    def __rsub__(self, other):
        return self.number - other.number


>>> x = Subtract(5)
>>> y = Subtract(10)
>>> x - y         # FAILS!

Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    x - y
TypeError: unsupported operand type(s) for -: 'Subtract' and 'Subtract'
>>> x.__rsub__(y) # WORKS!
-5

If I change __rsub__ to __sub__, it works.

What am I doing wrong? Also what is the purpose of these reverse operators?

like image 707
Randy Avatar asked Sep 21 '10 19:09

Randy


People also ask

What is the reverse operator in Python?

Python reversed() The reversed() method computes the reverse of a given sequence object and returns it in the form of a list.

How do you reverse a sequence in Python?

Strings can be reversed using slicing. To reverse a string, we simply create a slice that starts with the length of the string, and ends at index 0. The slice statement means start at string length, end at position 0, move with the step -1 (or one step backward).

How do you reverse a string list in Python?

To reverse a string with the list reverse() method, first, the string needs to be converted to a list using the list constructor. Then the list items are reversed in place with the reverse() method, and finally, the list items are joined into a string using the join() method.


2 Answers

The point of these methods is to allow this:

class MyNumber(object):
    def __init__(self, x):
        self.x = x

print 10 - MyNumber(9) # fails because 10.__sub__(MyNumber(9)) is unknown

class MyFixedNumber(MyNumber):
    def __rsub__(self, other):
        return MyNumber( other - self.x )

print 10 - MyFixedNumber(9) # MyFixedNumber(9).__rsub__(10) is defined

Very rarely useful though, usually you just use things of the same type and the direct __sub__

like image 120
Jochen Ritzel Avatar answered Sep 30 '22 13:09

Jochen Ritzel


From Python's Data model at http://docs.python.org/reference/datamodel.html :

These methods are called to implement the binary arithmetic operations (+, -, *, /, %, divmod(), pow(), **, <<, >>, &, ^, |) with reflected (swapped) operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. [2] For instance, to evaluate the expression x - y, where y is an instance of a class that has an __rsub__() method, y.__rsub__(x) is called if x.__sub__(y) returns NotImplemented.

However - both objects must not be of the same class - that means, that even if you put a __sub__ method returning NotImplemented on your example above, you will still get the same error: Python just assumes your Subtract class can't subtract from "Subtract" iobjects, no matter the order.

However, this works:

class Sub1(object):
    number = 5
    def __sub__(self, other):
        return NotImplemented

class Sub2(object):
    number = 2
    def __rsub__(self, other):
        return other.number - self.number


a = Sub1()
b = Sub2()

print a - b
like image 22
jsbueno Avatar answered Sep 30 '22 14:09

jsbueno