Issue with binary operator behavior.

This is the place for queries that don't fit in any of the other categories.

Issue with binary operator behavior.

Postby BlueKitties » Sat Sep 28, 2013 10:00 pm

I've encountered a rather baffling problem while using a custom datatype.

Essentially I have this:

Code: Select all
#This is from an application using Python 2.5.
import decimal

class MyNumberType(decimal.Decimal):
    #Overload the "/" operator.
    def __div__(self, other):
        result = decimal.Decimal(self) / decimal.Decimal(str(other))
        return MyNumberType(result)

if __name__ == "__main__":
    a = MyNumberType("10") / 2
    b = 10 / MyNumberType(2)
    print type(a)
    print type(b)


If you run the code, you'll notice a and b are different types -- binary arithmetic operators seem to call the arithmetic method defined by the leftmost argument. Therefore in the above code, a is a MyNumberType object, whereas b is a decimal.Decimal object.

The Python Interpreter seems to evaluate a / b as a.__div__(b), and b/a as b.__div__(a). Which raises the following issue: while I can customize the behavior of MyNumberType.__div__(), MyNumberType.__add__(), etc, I cannot seem to control the behavior when my class is the rightmost argument. Unfortunately, Python seems to happily operate on my custom datatype without raising any errors.

Now here's the issue: I'm rolling an application over from using one numeric type to my new custom numeric type, and the code base mixes datatypes, to catastrophic results. If I could set Python to allow me to define the behavior of the arithmetic functions for both left and right arguments, I'd be set. I can't seem to figure out how to do so. The other option would be to have Python raise an exception whenever datatypes are mixed, so I can at least be assured mathematical errors aren't going undetected.

Here's an example problem:

Code: Select all
x = MyNumberType("5")
y = 1 / x
if y > 1.0:
    print "y > 1.0 is true!"
else:
    print "y > 1.0 is false!"


1/x returns a decimal.Decimal object, and decimal.Decimal does not play nice with comparison operators (e.g. decimal.Decimal("1") > 1.5 evaluates as true.) Therefore in the above code example, 1/x <==> 1.__div__(x) returns a decimal.Decimal object, so then when the comparison happens, it incorrectly evaluates it as true. I've considered the possibility of modifying the builtin float and int datatypes to correctly handle my custom datatype, or to modify the decimal module's behavior, both of which I'm very leery of.

Suggestions? Ideas? Warnings?
BlueKitties
 
Posts: 4
Joined: Sat Sep 28, 2013 9:28 pm

Re: Issue with binary operator behavior.

Postby casevh » Sun Sep 29, 2013 2:43 am

For binary arithmetic operators, you also need to override the reversed methods: __rdiv__, __radd__, etc. See http://docs.python.org/2/reference/data ... eric-types for more details.

Code: Select all
#This is from an application using Python 2.5.
import decimal

class MyNumberType(decimal.Decimal):
    #Overload the "/" operator.
    def __div__(self, other):
        result = decimal.Decimal(self) / decimal.Decimal(str(other))
        return MyNumberType(result)

    def __rdiv__(self, other):
        result = decimal.Decimal(str(other)) / decimal.Decimal(self)
        return MyNumberType(result)

if __name__ == "__main__":
    a = MyNumberType("10") / 2
    b = 10 / MyNumberType(2)
    print type(a)
    print type(b)
casevh
 
Posts: 70
Joined: Sat Feb 09, 2013 7:35 am

Re: Issue with binary operator behavior.

Postby BlueKitties » Sun Sep 29, 2013 1:40 pm

You are an ANGEL, thank you so much! I was wondering how it was returning a decimal.Decimal object, that explains it. That just made life much easier.
BlueKitties
 
Posts: 4
Joined: Sat Sep 28, 2013 9:28 pm


Return to General Coding Help

Who is online

Users browsing this forum: snippsat, Yoriz and 4 guests