By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,925 Members | 727 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,925 IT Pros & Developers. It's quick & easy.

subclass of integers

P: n/a
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.

It's simple enough to construct a subclass of integers that behave in
this way:

class Nint(int):
def __add__(self,other):
if (other != None):
return self+other
else:
return None
def __radd__(self,other):
if (other != None):
return other+self
else:
return None
#...and so forth

However I have not been able to figure out how to make it so that
None, as well as an integer, could be an element of my class. My
preliminary impression is that I have to override int.__new__; but I
am uncertain how to do that and have been unable to find anything on
the web explaining that. Indeed I haven't been able to find much
about __new__ at all. Overriding this method of built-in classes
seems to be quite unusual.

I would very much appreciate anyone's help.

Sep 14 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
On Sep 14, 10:30 am, Mark Morss <mfmo...@aep.comwrote:
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.

It's simple enough to construct a subclass of integers that behave in
this way:

class Nint(int):
def __add__(self,other):
if (other != None):
return self+other
else:
return None
def __radd__(self,other):
if (other != None):
return other+self
else:
return None
#...and so forth

However I have not been able to figure out how to make it so that
None, as well as an integer, could be an element of my class. My
preliminary impression is that I have to override int.__new__; but I
am uncertain how to do that and have been unable to find anything on
the web explaining that. Indeed I haven't been able to find much
about __new__ at all. Overriding this method of built-in classes
seems to be quite unusual.

I would very much appreciate anyone's help.
I meant of course that arithmetic operations between integer elements
would return the same result as the corresponding integer operations,
not necessarily addition.

Sep 14 '07 #2

P: n/a
I would do something along the lines of the following, although it
only tests for integers and not floats, so would return 'None' for a
float.

class Nint(int):
def __add__(self, x, y):
if isinstance(x, int) and isinstance(y, int):
return x+y
return None

if __name__=='__main__':
N=Nint()
print N.__add__( 1, 2 )
print N.__add__( 1, None )

Sep 14 '07 #3

P: n/a
This would accept ints, floats, and decimal types.

import decimal

class Nint(int):
def __add__(self, x, y):
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)

Sep 14 '07 #4

P: n/a
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.

It's simple enough to construct a subclass of integers that behave in
this way:

class Nint(int):
def __add__(self,other):
if (other != None):
return self+other
else:
return None
def __radd__(self,other):
if (other != None):
return other+self
else:
return None
#...and so forth

However I have not been able to figure out how to make it so that
None, as well as an integer, could be an element of my class. My
preliminary impression is that I have to override int.__new__; but I
am uncertain how to do that and have been unable to find anything on
the web explaining that. Indeed I haven't been able to find much
about __new__ at all. Overriding this method of built-in classes
seems to be quite unusual.

I would very much appreciate anyone's help.
Do you really need to define one class that can represent None and the integers?
integers already behave as you want, except that they cannot do binary
operations with None. So why not simply define a NoneInt object?
>>class NoneInt(object):
... def _all_binops(self, other):
... if isinstance(other, (int, NoneInt)):
... return NoneInt()
... else:
... raise TypeError()
... __add__ = __radd__ = _all_binops
... # ...add comparison, unary methods to taste
... def __repr__(self):
... return "NoneInt()"
...
>>3+NoneInt()
NoneInt()
>>NoneInt()+2
NoneInt()
>>"s"+NoneInt()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 6, in _all_binops
TypeError
>>>
Getting back to your question, you can indeed override int.__new__ to return
something other than a raw int. This explains how and why:
http://www.python.org/download/relea....3/descrintro/
But unless there's more to your requirement than you set out above, it's
probably not worth the trouble.

HTH, Michael

Sep 14 '07 #5

P: n/a
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>
Sep 14 '07 #6

P: n/a
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.

It's simple enough to construct a subclass of integers that behave in
this way:

class Nint(int):
def __add__(self,other):
if (other != None):
return self+other
else:
return None
def __radd__(self,other):
if (other != None):
return other+self
else:
return None
#...and so forth

However I have not been able to figure out how to make it so that
None, as well as an integer, could be an element of my class. My
preliminary impression is that I have to override int.__new__; but I
am uncertain how to do that and have been unable to find anything on
the web explaining that. Indeed I haven't been able to find much
about __new__ at all. Overriding this method of built-in classes
seems to be quite unusual.

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...

-----8<--------------------------------------------------
class NoneInt(object):
def __init__(self, value):
self.value = value

def __add__(self, other):
if isinstance(other, NoneInt):
if None in (self.value, other.value):
return NoneInt(None)
return NoneInt(self.value + other.value)
elif isinstance(other, int):
if self.value is None:
return NoneInt(None)
return NoneInt(self.value + other)
else:
raise TypeError(
"unsupported operand type(s) for +: 'NoneInt'"
"and '%s'" % str(other.__class__.__name__)
)
__radd__ = __add__

def __str__(self):
return 'NoneInt(%s)' % str(self.value)
def main():
print '42? ', NoneInt(40) + NoneInt(2)
print '41? ', NoneInt(40) + 1
print '40? ', 25 + NoneInt(15)
print 'None? ', NoneInt(None)
print 'None? ', NoneInt(None) + 1
print 'None? ', 1 + NoneInt(None)
print 'Error? ', NoneInt(0) + 'spam'

if __name__ == '__main__':
main()
-----8<--------------------------------------------------

Ian

Sep 14 '07 #7

P: n/a
On Sep 14, 9:30 am, Mark Morss <mfmo...@aep.comwrote:
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.
Rather than subclassing int, why not just make a singleton NaN object
with overloaded arithmetic operators that all return NaN?

Sep 14 '07 #8

P: n/a
En Fri, 14 Sep 2007 20:16:36 -0300, Dan Bishop <da*****@yahoo.com>
escribi�:
On Sep 14, 9:30 am, Mark Morss <mfmo...@aep.comwrote:
>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.

Rather than subclassing int, why not just make a singleton NaN object
with overloaded arithmetic operators that all return NaN?
Like this:

class _NaN(object):

__instance = None

def __new__(cls):
if cls.__instance is None:
cls.__instance = super(_NaN, cls).__new__(cls)
return cls.__instance

__repr__ = __str__ = lambda self: 'NaN'

def unop(self): return self
def binop(self, other): return self
def terop(self, other, unused=None): return self
def false2(self, other): return False
def true2(self, other): return True
def notimpl(self): return NotImplemented

__abs__ = __invert__ = __neg__ = __pos__ = unop
__add__ = __and__ = __div__ = __divmod__ = __floordiv__ = __lshift__ =
__mod__ = __mul__ = __rshift__ = __or__ = __sub__ = __truediv__ = __xor__
= binop
__radd__ = __rand__ = __rdiv__ = __rdivmod__ = __rfloordiv__ =
__rlshift__ = __rmod__ = __rmul__ = __rpow__ = __rrshift__ = __ror__ =
__rsub__ = __rtruediv__ = __rxor__ = binop
__pow__ = terop
__lt__ = __le__ = __eq__ = __gt__ = __ge__ = false2
__ne__ = true2

del unop, binop, terop, false2, true2, notimpl

NaN = _NaN()

def test():
assert NaN + 1 is NaN
assert 1 & NaN is NaN
assert NaN * NaN is NaN

assert abs(NaN) is NaN
assert str(NaN)=="NaN"
assert repr(NaN)=="NaN"

assert not (NaN==NaN)
assert (NaN!=NaN)
assert not (NaN>NaN)
assert not (NaN<NaN)
assert not (NaN>=NaN)
assert not (NaN<=NaN)

assert not (NaN==1)
assert (NaN!=1)
assert not (NaN>1)
assert not (NaN<1)
assert not (NaN>=1)
assert not (NaN<=1)

assert not (1==NaN)
assert (1!=NaN)
assert not (1>NaN)
assert not (1<NaN)
assert not (1>=NaN)
assert not (1<=NaN)

assert cmp(NaN, 1)!=0
assert cmp(1, NaN)!=0
#assert cmp(NaN, NaN)!=0

assert NaN is _NaN()
assert NaN is type(NaN)()

test()

--
Gabriel Genellina

Sep 15 '07 #9

P: n/a
On Sep 14, 10:30 am, Mark Morss <mfmo...@aep.comwrote:
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.
No need to create a new class:

try:
result = a * b
except TypeError:
result = None

--
Roberto Bonvallet

Sep 16 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.