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 -- http://mail.python.org/mailman/listinfo/python-list