Subclassing int for a revolving control number

C

Chris Cioffi

Hello all!

I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count. This is for use as an X12
control number. Subclassing int and getting the display like I want
it was trivial, however what's the best way to make it such that:
990 + 1 = 991
991 + 1 = 992
....
998 + 1 = 999
999 + 1 = 001

Should I set any of the special functions like __sub__ to raise
NotImpemented and just make my own custom assignment and __add__
functions? (The other fucntions would make no sense in this
context...)

Is there an "on change" kind of meta-function? (Like the onChange
event in a GUI text control)

Chris
 
D

Dan Sommers

Hello all!
I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count. This is for use as an X12
control number. Subclassing int and getting the display like I want
it was trivial, however what's the best way to make it such that:
990 + 1 = 991
991 + 1 = 992
...
998 + 1 = 999
999 + 1 = 001
Should I set any of the special functions like __sub__ to raise
NotImpemented and just make my own custom assignment and __add__
functions? (The other fucntions would make no sense in this
context...)
Is there an "on change" kind of meta-function? (Like the onChange
event in a GUI text control)

That all sounds like overkill, at least to my old-fashioned, minimalist
tastes. Remember, too, that Python has a "we're all adults" philosophy.

Untested:

class X12ControlNumber:
def __init__( self, initialvalue = 1 ):
self.x = initialvalue
def increment( self ):
self.x += 1
if self.x == 1000
self.x = 1
def get( self ):
return self.x
# alternately:
def __str__( self ):
return '%03d' % self.x


x = X12ControlNumber( )
print x.get( ) # prints 1
x.increment( )
print x.get( ) # prints 2
x.increment( )
:
:
:
x.increment( )
print x.get( ) # prints 998
x.increment( )
print x.get( ) # prints 999
x.increment( )
print x.get( ) # prints 1

Regards,
Dan
 
D

Donn Cave

Quoth Chris Cioffi <[email protected]>:

| I'm trying to subclass int such that once it reaches a certain value,
| it flips back to the starting count. This is for use as an X12
| control number. Subclassing int and getting the display like I want
| it was trivial, however what's the best way to make it such that:
| 990 + 1 = 991
| 991 + 1 = 992
| ...
| 998 + 1 = 999
| 999 + 1 = 001
|
| Should I set any of the special functions like __sub__ to raise
| NotImpemented and just make my own custom assignment and __add__
| functions? (The other fucntions would make no sense in this
| context...)

Do bear in mind that ints don't change value. All you need is
1) control the initial value of the object (in __init__) and
2) make __add__ return your type instead of int.

class OI:
max = 16
def __init__(self, t):
if t > self.max:
t = t - self.max
self.value = t
def __add__(self, k):
return OI(self.value + k)
def __str__(self):
return str(self.value)
def __repr__(self):
return 'OI(%s)' % self.value
def __cmp__(self, v):
return cmp(self.value, v)

You could implement a mutable counter, but for most applications
the way int works is less confusing - like, what should this do?
i = OI(1)
j = i
i += 1
print i, j

Donn Cave, (e-mail address removed)
 
P

Paul McGuire

Chris Cioffi said:
I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count. This is for use as an X12
control number.
<remaining snipped...>

Why does this have to subclass int? I think you are falling into the basic
object trap of confusing "is-a" and "is-implemented-using-a" that eventually
turns inheritance hierarchies into a semantic contortion. Dan Sommers'
posted class looks to do just what you need, with no extra int baggage.

-- Paul
 
S

Scott David Daniels

Chris said:
I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count....

Others have given you the real answer -- don't bother with this.
However, it looks like fun:

class Clock(int):
def __add__(self, other):
return self.__class__(super(Clock, self
).__add__(other) % 12 or 12)
__radd__ = __add__

def __sub__(self, other):
return self + -other

def __rsub__(self, other):
return self.__class__(-self + 12) + other

def __repr__(self):
return '%s(%s)' % (type(self).__name__, int(self))

-Scott David Daniels
(e-mail address removed)
 
C

Chris Cioffi

Why does this have to subclass int? I think you are falling into the basic
object trap of confusing "is-a" and "is-implemented-using-a" that eventually
turns inheritance hierarchies into a semantic contortion. Dan Sommers'
posted class looks to do just what you need, with no extra int baggage.

Paul,

I think you've hit the answer. I shouldn't think about the control
number as an int.

The whole thing came up b/c I've been wanting to play with classes
derived from built-ins and though that this was a good fit. Once it's
put in a more realistic context my not so great rationale doesn't
quite make as much sense.

Thanks for the comments all...

Chris
 
P

Peter Otten

Chris said:
I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count. This is for use as an X12
control number. Subclassing int and getting the display like I want
it was trivial, however what's the best way to make it such that:
990 + 1 = 991
991 + 1 = 992
...
998 + 1 = 999
999 + 1 = 001

Should I set any of the special functions like __sub__ to raise
NotImpemented and just make my own custom assignment and __add__
functions? (The other fucntions would make no sense in this
context...)

OK, here's my take at the problem.

Peter


class IntN(int):
""" Base class for int % N """
def __new__(cls, value):
value = value % cls.N
if value < 0:
value = cls.N - value
return int.__new__(cls, value)
def __add__(self, other):
return self.__class__(int.__add__(self, other))
def __sub__(self, other):
return self.__class__(int.__sub__(self, other))

def makeNoimp(name):
""" generate a method that raises a NotImplemented exception """
def noimp(self, *args):
raise NotImplementedError("method %s() not implemented" % name)
return noimp

# shade the methods inherited from int
for name in "__mul__ __div__".split():
setattr(IntN, name, makeNoimp(name))


class IntK(IntN):
""" A weird way of implementing your (weird) specification """
N = 999
def __str__(self):
return str(1 + self)
__repr__ = __str__

if __name__ == "__main__":
first = IntK(995)
for i in range(10):
print first,
first += 1
print

first = IntK(5)
for i in range(10):
print first,
first -= 1
print

try:
first * 3
except NotImplementedError, e:
print e
 
M

Michele Simionato

Chris Cioffi said:
Hello all!

I'm trying to subclass int such that once it reaches a certain value,
it flips back to the starting count. This is for use as an X12
control number. Subclassing int and getting the display like I want
it was trivial, however what's the best way to make it such that:
990 + 1 = 991
991 + 1 = 992
...
998 + 1 = 999
999 + 1 = 001

Should I set any of the special functions like __sub__ to raise
NotImpemented and just make my own custom assignment and __add__
functions? (The other fucntions would make no sense in this
context...)

Is there an "on change" kind of meta-function? (Like the onChange
event in a GUI text control)

If you are not interested in subtracting the counter, this is a nice
solution:
.... print i

CTRL-C when you are tired ;)


Michele Simionato
 
A

Antoon Pardon

Op 2004-07-16 said:
That all sounds like overkill, at least to my old-fashioned, minimalist
tastes. Remember, too, that Python has a "we're all adults" philosophy.

Sorry, but remarks like the one that follows, let me doubt that.

from http://docs.python.org/api/threads.html:

| To prevent naive misuse, you must write your own C extension to call
| this.
 
S

Stephen Ferg

I think the simplest solution would be just to use a generator...

************************************
def rollover(argMaxNumber=20):
while True:
for i in range(1, argMaxNumber+1):
yield i

########### test the rollover generator...

r = rollover(5)
for i in range(33):
print i, "=", r.next()
*************************************
 
C

Calvin Spealman

Personally, rather than all these suggestions of python-written classes or
of itertools.cycle, I would like a C-extension module with something like
this. All it would have to be is an actually C int value with no bounds
checking. This would be usually for working with low-level data, like
bitmaps or compressed data, where you can't have longs and where you need
good performance on simple arithmetic.
 
M

Matteo Dell'Amico

Stephen said:
I think the simplest solution would be just to use a generator...

************************************
def rollover(argMaxNumber=20):
while True:
for i in range(1, argMaxNumber+1):
yield i

This can also be spelled as itertools.cycle(xrange(max_number)).
 
C

Christopher T King

This can also be spelled as itertools.cycle(xrange(max_number)).

Watch out: itertools.cycle doesn't restart the generator when it's
exhausted; instead, it keeps a copy of all the items returned by the
iterator and loops over them.
 
C

Christopher T King

Personally, rather than all these suggestions of python-written classes or
of itertools.cycle, I would like a C-extension module with something like
this. All it would have to be is an actually C int value with no bounds
checking. This would be usually for working with low-level data, like
bitmaps or compressed data, where you can't have longs and where you need
good performance on simple arithmetic.

numarray does this:
2

It also greatly speeds up performance on the vector operations needed in
processing bitmaps, etc.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top