simple integer subclass

  • Thread starter Andreas Pfrengle
  • Start date
A

Andreas Pfrengle

I'm trying to define a subclass of int called int1. An int1-object
shall behave exactly like an int-object, with the only difference that
the displayed value shall be value + 1 (it will be used to display
array indices starting at 1 instead of 0). Right now I have:

class int1(int):
def __str__(self):
return int.__str__(self + 1)

However, if I calculate with int1 and int- (or other number) objects,
the result is always coerced to an int (or other number object), e.g:
a = int1(5)
b = 5
print a # "6"
print a+b #"10"

How can I tell int1 to be the "default integer object"? Do I need to
overload *every* mathematical operation method of int, or is there an
easier way?
 
S

samwyse

I'm trying to define a subclass of int called int1. An int1-object
shall behave exactly like an int-object, with the only difference that
the displayed value shall be value + 1 (it will be used to display
array indices starting at 1 instead of 0). Right now I have:

class int1(int):
    def __str__(self):
        return int.__str__(self + 1)

However, if I calculate with int1 and int- (or other number) objects,
the result is always coerced to an int (or other number object), e.g:
a = int1(5)
b = 5
print a      # "6"
print a+b  #"10"

How can I tell int1 to be the "default integer object"? Do I need to
overload *every* mathematical operation method of int, or is there an
easier way?

I had a similar problem a few years ago, and couldn't find a solution
then. The thread from back then may shed some light on your problem.
http://groups.google.com/group/comp...hread/thread/10cfe2affc265ac/2ad03b121c1c6489
 
C

Carl Banks

I'm trying to define a subclass of int called int1. An int1-object
shall behave exactly like an int-object, with the only difference that
the displayed value shall be value + 1 (it will be used to display
array indices starting at 1 instead of 0). Right now I have:

class int1(int):
    def __str__(self):
        return int.__str__(self + 1)

However, if I calculate with int1 and int- (or other number) objects,
the result is always coerced to an int (or other number object), e.g:
a = int1(5)
b = 5
print a      # "6"
print a+b  #"10"

How can I tell int1 to be the "default integer object"? Do I need to
overload *every* mathematical operation method of int, or is there an
easier way?

(Preface: I normally don't offer recommendations without answering the
question as asked, but once in a while it has to be done.)

I **highly** recommend against this approach.

You are creating an object that differs from a built-in, int, in a
highly misleading way that only makes sense in a very limited context,
and this object's modified behavior gives no clue that it's been
modified in such as way. (That is, it's not possible to tell if the
object's not a regular int just by looking at __str__()'s return
value.) To make matters worse, you want to program this object to
coerce other integers, so there's a risk of these objects escaping
from the context where they make sense.

This is just a bad idea. The type is not the place to implement
behavior that makes sense only in a limited context. Instead, do
something like this:

print "Item %d is %s." % (i+1, s)


Carl Banks
 
R

rantingrick

I'm trying to define a subclass of int called int1. An int1-object
shall behave exactly like an int-object, with the only difference that
the displayed value shall be value + 1 (it will be used to display
array indices starting at 1 instead of 0)

Is zero based indexing that bad for you? I also think this is a very
bad idea unless you can offer a sensible use case -- for which i
cannot imagine.
 
A

Andreas Pfrengle

You are creating an object that differs from a built-in, int, in a
highly misleading way that only makes sense in a very limited context,
and this object's modified behavior gives no clue that it's been
modified in such as way.  (That is, it's not possible to tell if the
object's not a regular int just by looking at __str__()'s return
value.)  To make matters worse, you want to program this object to
coerce other integers, so there's a risk of these objects escaping
from the context where they make sense.

This is just a bad idea.  The type is not the place to implement
behavior that makes sense only in a limited context.  Instead, do
something like this:

print "Item %d is %s." % (i+1, s)


I see your concerns. I started with the approach to add +1 directly
before displaying the int. However, since there are some variables
that shall be displayed normally and others that are indices I want to
show starting at 1, I thought the easiest way would be to define a
type that does the job, then I would only need to define it once and
not take care everywhere whether I have a normal variable or a
displayed index.
Thinking about it, it might really be dangerous to coerce always to
int1, since sometimes I might want a normal int as result (I can't
tell yet for sure).
I'm just thinking about only overloading the operations if the int1 is
on the left-hand side (so __op__ coerces to int1, while __rop__
doesn't). This would make operations non-commutative - but I also
would need to put more brains in every calculation, which could
finally take more effort than only "upgrading" the display :-???
Seems I end up with your suggestion - if noone else has an idea ;-)

The application will be a browsergame, and most gamers start counting
at 1, so they would probably wonder about a "level 0 item" ;-)
If there didn't already exist lots of code, I would redesign the whole
data-structure - I think that's "lessons learned" for the next project
-.-
 
J

Jean-Michel Pichavant

Andreas said:
You are creating an object that differs from a built-in, int, in a
highly misleading way that only makes sense in a very limited context,
and this object's modified behavior gives no clue that it's been
modified in such as way. (That is, it's not possible to tell if the
object's not a regular int just by looking at __str__()'s return
value.) To make matters worse, you want to program this object to
coerce other integers, so there's a risk of these objects escaping
from the context where they make sense.

This is just a bad idea. The type is not the place to implement
behavior that makes sense only in a limited context. Instead, do
something like this:

print "Item %d is %s." % (i+1, s)


I see your concerns. I started with the approach to add +1 directly
before displaying the int. However, since there are some variables
that shall be displayed normally and others that are indices I want to
show starting at 1, I thought the easiest way would be to define a
type that does the job, then I would only need to define it once and
not take care everywhere whether I have a normal variable or a
displayed index.
Thinking about it, it might really be dangerous to coerce always to
int1, since sometimes I might want a normal int as result (I can't
tell yet for sure).
I'm just thinking about only overloading the operations if the int1 is
on the left-hand side (so __op__ coerces to int1, while __rop__
doesn't). This would make operations non-commutative - but I also
would need to put more brains in every calculation, which could
finally take more effort than only "upgrading" the display :-???
Seems I end up with your suggestion - if noone else has an idea ;-)

The application will be a browsergame, and most gamers start counting
at 1, so they would probably wonder about a "level 0 item" ;-)
If there didn't already exist lots of code, I would redesign the whole
data-structure - I think that's "lessons learned" for the next project
-.-

The level of an item is attribute of this item, not an index in a list.
You may have an issue with your design, using an improper structure.

In a more general manner, given your example I don't see why you should
expose the index of an element in an internal list to the user.

JM
 
J

Jean-Michel Pichavant

Jean-Michel Pichavant said:
Andreas said:
You are creating an object that differs from a built-in, int, in a
highly misleading way that only makes sense in a very limited context,
and this object's modified behavior gives no clue that it's been
modified in such as way. (That is, it's not possible to tell if the
object's not a regular int just by looking at __str__()'s return
value.) To make matters worse, you want to program this object to
coerce other integers, so there's a risk of these objects escaping
from the context where they make sense.

This is just a bad idea. The type is not the place to implement
behavior that makes sense only in a limited context. Instead, do
something like this:

print "Item %d is %s." % (i+1, s)


I see your concerns. I started with the approach to add +1 directly
before displaying the int. However, since there are some variables
that shall be displayed normally and others that are indices I want to
show starting at 1, I thought the easiest way would be to define a
type that does the job, then I would only need to define it once and
not take care everywhere whether I have a normal variable or a
displayed index.
Thinking about it, it might really be dangerous to coerce always to
int1, since sometimes I might want a normal int as result (I can't
tell yet for sure).
I'm just thinking about only overloading the operations if the int1 is
on the left-hand side (so __op__ coerces to int1, while __rop__
doesn't). This would make operations non-commutative - but I also
would need to put more brains in every calculation, which could
finally take more effort than only "upgrading" the display :-???
Seems I end up with your suggestion - if noone else has an idea ;-)

The application will be a browsergame, and most gamers start counting
at 1, so they would probably wonder about a "level 0 item" ;-)
If there didn't already exist lots of code, I would redesign the whole
data-structure - I think that's "lessons learned" for the next project
-.-

The level of an item is attribute of this item, not an index in a list.
You may have an issue with your design, using an improper structure.

In a more general manner, given your example I don't see why you
should expose the index of an element in an internal list to the user.

JM

"If there didn't already exist lots of code, I would redesign the whole
data-structure"

sorry I didn't get this one at first read, my comment is pretty much
useless.

JM
 
R

Roald de Vries

Hi Andreas,

I'm trying to define a subclass of int called int1. An int1-object
shall behave exactly like an int-object, with the only difference that
the displayed value shall be value + 1 (it will be used to display
array indices starting at 1 instead of 0). Right now I have:

class int1(int):
def __str__(self):
return int.__str__(self + 1)

However, if I calculate with int1 and int- (or other number) objects,
the result is always coerced to an int (or other number object), e.g:
a = int1(5)
b = 5
print a # "6"
print a+b #"10"

How can I tell int1 to be the "default integer object"? Do I need to
overload *every* mathematical operation method of int, or is there an
easier way?

Maybe you could use:
1) a dict with keys 1..n
2) a simple list (or iterable) subclass with 1-based indices.

class list1(list):
def __new__(cls, *args, **kwargs):
return list.__new__(cls, *args, **kwargs)

def __getitem__(self, key):
return list.__getitem__(self, key-1)

... etcetera


Cheers, Roald
 
S

Stefan Schwarzer

Hi Andreas,

Thinking about it, it might really be dangerous to coerce always to
int1, since sometimes I might want a normal int as result (I can't
tell yet for sure).

Yes, that way your problem may shift from inconvenient to
outright hairy. ;-)
The application will be a browsergame, and most gamers start counting
at 1, so they would probably wonder about a "level 0 item" ;-)
If there didn't already exist lots of code, I would redesign the whole
data-structure - I think that's "lessons learned" for the next project

What about

def _index_to_level(index):
return index + 1

with this or a different name? This admittedly is longer
than writing `something + 1` but in the latter case you
might wonder what the addition is for, i. e. if it's really
a level offset calculation or something else.

Stefan
 
A

Andreas Pfrengle

Hello everyone,

thanks for all the suggestions. I did effort to redesign parts of the
data structure the last days, but not all (only those I could easily
keep track of in my code).
For the rest I add +1 before the presentation and comment it. Seems
the easiest way now.

Andreas
 

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,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top