How to avoid overflow errors

James Stroud jstroud at mbi.ucla.edu
Sat Sep 15 05:45:10 EDT 2007


Steven D'Aprano wrote:
> On Fri, 14 Sep 2007 18:19:45 -0700, James Stroud wrote:
> 
>>> How do I subclass int and/or long so that my class also auto-converts
>>> only when needed?
>>>
>> Use __new__.
> 
> The disadvantage of that is that your example code requires me to 
> duplicate my methods in the long version and the int version. It's easy 
> enough to work around that (class factory function) but it just seems all 
> rather untidy...


The __new__ method is where you implement such decisions. There is no 
"tidier" way for one class "auto-convert" to another class, which is 
what you asked for (it says so right up there ^). So, if you don't like 
the answer, don't ask the question.

Despite its unseemly appearance because of all the underscores, it is 
the natural way in python (to do what you have asked and not something 
which you didn't ask).

The way to avoid duplicating methods (which is what you are asking for, 
no?) while still allowing your classes to maintain their identities is 
by using mixins:


class MyModulatingMixin(object):
   def modulate(self, sum):
     if self.modulus is None:
       return self.__class__(sum)
     else:
       return self.__class__(sum % self.modulus)
   def __add__(self, other):
     sum = long.__add__(long(self), long(other))
     return self.modulate(sum)
   def __mul__(self, other):
     sum = long.__mul__(long(self), long(other))
     return self.modulate(sum)

class MyLong(long):
   def __new__(cls, v, m=None):
     obj = long.__new__(cls, v)
     obj.modulus = m
     return obj

class MyInt(int):
   def __new__(cls, v, m=None):
     try:
       obj = int.__new__(cls, v)
       obj.modulus = m
     except OverflowError:
       obj = MyLong(v, m)
     return obj

for cls in MyLong, MyInt:
   cls.__bases__ = (MyModulatingMixin,) + cls.__bases__


py> i = MyInt(51)
py> j = MyInt(40, 7)
py> k = MyLong(2, 13)
py> i + j
91
py> j + k
0
py> k + j
3L
py> i * k
102
py> type(i * k)
<class '__main__.MyInt'>
py> k * i
11L
py> type(k * i)
<class '__main__.MyLong'>


James



More information about the Python-list mailing list