Usefulness of subclassing builtin number types
Gerhard Häring
gerhard.haering at gmx.de
Sun Dec 15 11:54:28 EST 2002
I'd like to subclass some builtin number types, and int in particular.
And I want (of course) that this subclassing is 'sticky', so if I do a:
x = MyInt(25)
x *= 2
I want 'x' to stay of the class MyInt. I even can't think of any use
case right now where I'd *not* want this. The problem? Python doesn't do
this, instead it always returns ints.
Ok, I know that this saves one indirection per operation and is thus a
performance gain for int itself, as long as it's not subclassed. But
*if* it is subclassed, this behaviour is really a pain in the arse.
My current experimentation lead me to this code:
#v+
from __future__ import division
class StickyInt(int):
__slots__ = []
def __iadd__(self, other):
return self.__class__(int.__radd__(self, other))
def __add__(self, other):
return self.__class__(int.__add__(self, other))
def __sub__(self, other):
return self.__class__(int.__sub__(self, other))
def __mul__(self, other):
return self.__class__(int.__mul__(self, other))
def __div__(self, other):
return self.__class__(int.__div__(self, other))
def __divmod__(self, other):
return map(self.__class__, int.__divmod__(self, other))
def __mod__(self, other):
return self.__class__(int.__mod__(self, other))
def __pow__(self, other, modulus=None):
return self.__class__(int.__pow__(self, other, modulus))
def __floordiv__(self, other):
return self.__class__(int.__floordiv__(self, other))
def __abs__(self):
return self.__class__(int.__abs__(self))
def __pos__(self):
return self.__class__(int.__pos__(self))
def __neg__(self):
return self.__class__(int.__neg__(self))
def __nonzero__(self):
return self.__class__(int.__nonzero__(self))
def __invert__(self):
return self.__class__(int.__invert__(self))
def __or__(self, other):
return self.__class__(int.__or__(self, other))
def __and__(self, other):
return self.__class__(int.__and__(self, other))
def __xor__(self, other):
return self.__class__(int.__xor__(self, other))
def __lshift__(self, other):
return self.__class__(int.__lshift__(self, other))
def __rshift__(self, other):
return self.__class__(int.__rshift__(self, other))
# Behaviour of superclass is ok for __truediv__, __complex__, __int__,
# __long__, __float__, __oct__, __hex__, __cmp__, __str__, __repr__
class MyInt(StickyInt):
pass
if __name__ == "__main__":
x = MyInt(25000)
x = abs(x + 1)
print type(x), x
print x+1
#v-
... which is a little *cough* more verbose than I'd want it to be. To
be honest, other than issubclass(MyInt, int) is now true I don't think
this gives me *any* advantage over previous versions of Python.
Questions:
1) should the behaviour be changed and the necessary additional
indirection introduced for builtin types?
2) if not, and there are performance reasons for keeping it like it
is, should something like my StickyInt be put into the Python
library?
3) or am I boldly going where no Python programmer has gone before?
;-) [1]
Gerhard
[1] looking forward to Star Trek - Nemesis :)
--
Favourite database: http://www.postgresql.org/
Favourite programming language: http://www.python.org/
Combine the two: http://pypgsql.sf.net/
More information about the Python-list
mailing list