Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

__iadd__ useless in sub-classed int

5 views
Skip to first unread message

samwyse

unread,
Dec 6, 2007, 2:03:49 PM12/6/07
to
For whatever reason, I need an inproved integer. Sounds easy, let's
just subclass int:

>>> class test(int):
pass

Now let's test it:

>>> zed=test(0)
>>> zed.__class__
<class '__main__.test'>
>>> zed
0

So far, so good. Now let's try incrementing:

>>> zed+=1
>>> zed
1
>>> zed.__class__
<type 'int'>

WTF??!
Is this a bug or is it the inevitable result of optimizing for the
case where all integers are indistinguishable?

Diez B. Roggisch

unread,
Dec 6, 2007, 2:12:58 PM12/6/07
to
samwyse schrieb:

There has been a lengthe thread over the semantics of __iadd__ a few
weeks ago. It _can_ modify the object in question in-place (something
not possible for ints anyway), but it will ALWAYS return a reference
which will be set to the left-hand-side.

zed = zed.__iadd__(1)

So - you need to overload the __iadd__-method to return a test-instance.

Diez

samwyse

unread,
Dec 6, 2007, 4:02:18 PM12/6/07
to

Thanks! I'd missed that thread, googling found it but it didn't look
noteworthy at first glance. I've not yet read the entire thread, but
I did see a reference to PEP 203.

) So, given the expression:
)
) x += y
)
) The object `x' is loaded, then `y' is added to it, and the
) resulting object is stored back in the original place.

That agrees with what I'm seeing, all right. The problem is, the
resulting object has a different type, which seems to violate the
spirit of a later paragraph:

) Writing the above expression as
)
) <x> <operator>= <y>
)
) is both more readable and less error prone, because it is
) instantly obvious to the reader that it is <x> that is being
) changed, and not <x> that is being replaced by something almost,
) but not quite, entirely unlike <x>.

And that's my complaint. The value in <zed> is being replaced by
something almost, but not quite, identical to the original value.
Python's internal implementation of __iadd__ for <int> isn't returning
<self>, it's returning a new value belonging to the super-class. My
whole point is overloading <int> was that I'd hoped to avoid having to
write a bunch of methods to perform in-place modifications. Looks
like I stuck, however.

Neil Cerutti

unread,
Dec 6, 2007, 4:17:57 PM12/6/07
to
On 2007-12-06, samwyse <sam...@gmail.com> wrote:
> And that's my complaint. The value in <zed> is being replaced
> by something almost, but not quite, identical to the original
> value. Python's internal implementation of __iadd__ for <int>
> isn't returning <self>, it's returning a new value belonging to
> the super-class.

int.__iadd__ cannot return self because int instances are
immutable. In order to return self it would first have to change
what's unchangeable.

> My whole point is overloading <int> was that
> I'd hoped to avoid having to write a bunch of methods to
> perform in-place modifications. Looks like I stuck, however.

You have to implement only the operations you actually use. So to
save yourself drudge-work, use fewer operations. ;-)

--
Neil Cerutti

Chris Mellon

unread,
Dec 6, 2007, 4:19:45 PM12/6/07
to pytho...@python.org

The phrasing is a little awkward. Instead of "store" say "bound to the
same name as"

> ) Writing the above expression as
> )
> ) <x> <operator>= <y>
> )
> ) is both more readable and less error prone, because it is
> ) instantly obvious to the reader that it is <x> that is being
> ) changed, and not <x> that is being replaced by something almost,
> ) but not quite, entirely unlike <x>.
>
> And that's my complaint. The value in <zed> is being replaced by
> something almost, but not quite, identical to the original value.
> Python's internal implementation of __iadd__ for <int> isn't returning
> <self>, it's returning a new value belonging to the super-class. My
> whole point is overloading <int> was that I'd hoped to avoid having to
> write a bunch of methods to perform in-place modifications. Looks
> like I stuck, however.
>

Remember that in Python, name binding (which is to say, pure
assignment) is never a mutating operation. It's purely internal to the
namespace it occurs in. So even when augmented assignment returns
self, it still results in a normal Python assignment.

You're going to be struggling against the grain trying to implement a
mutable int anyway, you won't be able to make "foo = 10" mutate the
int, and even if you do create one you probably don't want it to
return true for isinstance(foo, int).

MonkeeSage

unread,
Dec 7, 2007, 1:01:28 AM12/7/07
to

I've wondered about this myself. Seems to me, to prevent clobbering
subclasses, __iadd__ (and all of the integer and float and whatever)
methods that return new instances, should work like this (obviously I
mean in the C backend, this is just to show the behavior):

def __iadd__(self, other):
return self.__class__(self + other)

Regards,
Jordan

Gabriel Genellina

unread,
Dec 7, 2007, 1:45:41 AM12/7/07
to pytho...@python.org
En Fri, 07 Dec 2007 03:01:28 -0300, MonkeeSage <Monke...@gmail.com>
escribió:

> I've wondered about this myself. Seems to me, to prevent clobbering
> subclasses, __iadd__ (and all of the integer and float and whatever)
> methods that return new instances, should work like this (obviously I
> mean in the C backend, this is just to show the behavior):
>
> def __iadd__(self, other):
> return self.__class__(self + other)

This would slow down *all* of Python, and is only useful for those who
actually inherit from some builtin class (not so common)

--
Gabriel Genellina

MonkeeSage

unread,
Dec 7, 2007, 3:37:11 AM12/7/07
to
On Dec 7, 12:45 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
> En Fri, 07 Dec 2007 03:01:28 -0300, MonkeeSage <MonkeeS...@gmail.com>

I understand why it doesn't. It just *seems* like it should work that
way when you first run into it (and has bitten me a couple times
before). But then, I'm not Dutch. :)

Regard,
Jordan

A.T.Hofkamp

unread,
Dec 10, 2007, 6:46:39 AM12/10/07
to
On 2007-12-06, samwyse <sam...@gmail.com> wrote:

I think you don't want this.

Suppose I keep track of addition information (eg a boolean "is_even = value ==
value//2") Since the base class doesn't know about this, it may return an
incorrect instance.

Albert

0 new messages