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

__iadd__ useless in sub-classed int

P: n/a
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?
Dec 6 '07 #1
Share this Question
Share on Google+
7 Replies


P: n/a
samwyse schrieb:
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?
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
Dec 6 '07 #2

P: n/a
On Dec 6, 1:12 pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
samwyse schrieb:
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?

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.
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 <xthat is being
) changed, and not <xthat is being replaced by something almost,
) but not quite, entirely unlike <x>.

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

P: n/a
On Dec 6, 2007 3:02 PM, samwyse <sa*****@gmail.comwrote:
>
On Dec 6, 1:12 pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
samwyse schrieb:
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?
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.

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:
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 <xthat is being
) changed, and not <xthat is being replaced by something almost,
) but not quite, entirely unlike <x>.

And that's my complaint. The value in <zedis being replaced by
something almost, but not quite, identical to the original value.
Python's internal implementation of __iadd__ for <intisn't returning
<self>, it's returning a new value belonging to the super-class. My
whole point is overloading <intwas 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).
Dec 6 '07 #4

P: n/a
On Dec 6, 3:02 pm, samwyse <samw...@gmail.comwrote:
On Dec 6, 1:12 pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
samwyse schrieb:
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?
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.

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 <xthat is being
) changed, and not <xthat is being replaced by something almost,
) but not quite, entirely unlike <x>.

And that's my complaint. The value in <zedis being replaced by
something almost, but not quite, identical to the original value.
Python's internal implementation of __iadd__ for <intisn't returning
<self>, it's returning a new value belonging to the super-class. My
whole point is overloading <intwas that I'd hoped to avoid having to
write a bunch of methods to perform in-place modifications. Looks
like I stuck, however.
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
Dec 7 '07 #5

P: n/a
En Fri, 07 Dec 2007 03:01:28 -0300, MonkeeSage <Mo********@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

Dec 7 '07 #6

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

P: n/a
On 2007-12-06, samwyse <sa*****@gmail.comwrote:
On Dec 6, 1:12 pm, "Diez B. Roggisch" <de...@nospam.web.dewrote:
And that's my complaint. The value in <zedis being replaced by
something almost, but not quite, identical to the original value.
Python's internal implementation of __iadd__ for <intisn't returning
<self>, it's returning a new value belonging to the super-class. My
whole point is overloading <intwas that I'd hoped to avoid having to
write a bunch of methods to perform in-place modifications. Looks
like I stuck, however.
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

Dec 10 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.