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