subclass of integers

Ian Clark iclark at mail.ewu.edu
Fri Sep 14 18:38:11 EDT 2007


Ian Clark wrote:
> Mark Morss wrote:
>> I would like to construct a class that includes both the integers and
>> None.  I desire that if x and y are elements of this class, and both
>> are integers, then arithmetic operations between them, such as x+y,
>> return the same result as integer addition.  However if either x or y
>> is None, these operations return None.
>>
>> (snip)
>>
>> I would very much appreciate anyone's help.
> 
> My thought would be rather than trying to cram None into a subclass of 
> int, to use delegation instead...
> 
> (snip)
> 
> Ian

A more robust implementation that accounts for ints/longs as well as 
implementing more operations...

-----8<--------------------------------------------------
import operator

class NoneInt(object):
     _LEFT = 1
     _RIGHT = 2


     def __init__(self, value):
         self.value = value


     def _get_arguments(self, other, direction=_LEFT):
         """ Given a direction (left or right), returns the left hand
         side and right hand side values. """

         if direction == self._LEFT:
             lhs = self.value
             if isinstance(other, (int, long, type(None))):
                 rhs = other
             else:
                 rhs = other.value
         elif direction == self._RIGHT:
             rhs = self.value
             if isinstance(other, (int, long, type(None))):
                 lhs = other
             else:
                 lhs = other.value
         else:
             raise ValueError('direction must be either _LEFT or _RIGHT')
         return (lhs, rhs)


     def _operation(op, direction):
         """ Given a direction and an operation will return a function
         that calls the operation with the arguments in the correct
         order. """

         def func(self, other):
             if not isinstance(other, (int, long, NoneInt, type(None))):
                 fmt = "unsupported operand type(s) for %s: 'NoneInt' 
and '%s'"
                 args =  (op.__name__, other.__class__.__name__)
                 raise TypeError(fmt % args)

             lhs, rhs = self._get_arguments(other, direction)

             if None in (lhs, rhs):
                 return NoneInt(None)
             return NoneInt(op(lhs, rhs))
         return func


     __add__ = _operation(operator.add, _LEFT)
     __radd__ = _operation(operator.add, _RIGHT)
     __sub__ = _operation(operator.sub, _LEFT)
     __rsub__ = _operation(operator.sub, _RIGHT)
     __div__ = _operation(operator.div, _LEFT)
     __rdiv__ = _operation(operator.div, _RIGHT)
     __mul__ = _operation(operator.mul, _LEFT)
     __rmul__ = _operation(operator.mul, _RIGHT)
     # ... etc


     def __eq__(self, other):
         lhs, rhs = self._get_arguments(other)
         return lhs == rhs


     def __nonzero__(self):
         return bool(self.value)


     def __str__(self):
         return 'NoneInt(%s)' % str(self.value)

     __repr__ = __str__
-----8<--------------------------------------------------

Ian




More information about the Python-list mailing list