subclass of integers
Bruno Desthuilliers
bdesth.quelquechose at free.quelquepart.fr
Sat Sep 15 13:28:11 EDT 2007
Zentrader a écrit :
> This would accept ints, floats, and decimal types.
It doesn't...
> import decimal
Useless
> class Nint(int):
> def __add__(self, x, y):
The prototype for __add__ is __add__(self, other)
> try:
> return x+y
> except:
> return None
>
> if __name__=='__main__':
> N=Nint()
> print N.__add__( 1, 2 )
> print N.__add__( 1, None )
> print N.__add__(decimal.Decimal("2"), decimal.Decimal("3"))
> print N.__add__(decimal.Decimal("2"), 3)
>
i = Nint(42)
i + 33
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: __add__() takes exactly 3 arguments (2 given)
The following works better (at least for integers - which is what the OP
saked for), but it's still not the solution:
import types
class Nint(int):
def __new__(cls, value=0):
# doesn't work with Nint(None)...
return int.__new__(cls, value)
def __add__(self, other):
if isinstance(other, int):
return int.__add__(self, other)
elif isinstance(other, types.NoneType):
return None
else:
err = "unsupported operand type(s) for +: '%s' and '%s'" \
% (type(self), type(other))
raise TypeError(err)
i = Nint(42)
=> 42
i + None
=> None
i + "allo"
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/tmp/python-8683q3Z", line 19, in __add__
TypeError: unsupported operand type(s) for +: '<class '__main__.Nint'>'
and '<type 'str'>'
Fo some reasons I'm not sure about and didn't have time to investigate
(some guru around ?), trying to catch a TypeError in __add__ failed -
raising a TypeError ! But anyway, this isn't the correct solution since
we don't want Nint.__add__ to return None when other is neither an int
nor None.
Anyway, this still doesn't solves the OP's problem since it doesn't
satisfy isinstance(Nint(None), NoneType). I tried making Nint a subclass
of both int and NoneType, but it doesn't work for obvious reasons (None
is a singleton). The only funny thing here is the error message when
trying to call NoneType.__new__:
>>> NoneType.__new__(NoneType)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: object.__new__(NoneType) is not safe, use NoneType.__new__()
>>>
<OP>
The best I could come with is:
from types import NoneType
class Nint(int, NoneType):
def __new__(cls, value=None):
# by default, will return Nint(0) even if value is None
return int.__new__(cls, value)
def __add__(self, other):
if isinstance(other, int):
return int.__add__(self, other)
elif isinstance(other, NoneType):
return None
else:
err = "unsupported operand type(s) for +: '%s' and '%s'" \
% (type(self), type(other))
raise TypeError(err)
# other __functions__ to implement, left as an exercise to the OP
__all__ = [Nint]
Maybe some guru around will find something better, but I have some doubts...
</OP>
More information about the Python-list
mailing list