[ python-Bugs-1633630 ] class derived from float evaporates under +=

SourceForge.net noreply at sourceforge.net
Tue Jan 16 18:40:55 CET 2007


Bugs item #1633630, was opened at 2007-01-11 15:49
Message generated for change (Comment added) made by josiahcarlson
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1633630&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Type/class unification
Group: Python 2.5
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: Matthias Klose (doko)
Assigned to: Nobody/Anonymous (nobody)
Summary: class derived from float evaporates under +=

Initial Comment:
[forwarded from http://bugs.debian.org/345373]

There seems to be a bug in classes derived from float.

For instance, consider the following:

>>> class Float(float):
...     def __init__(self, v):
...             float.__init__(self, v)
...             self.x = 1
...
>>> a = Float(2.0)
>>> b = Float(3.0)
>>> type(a)
<class '__main__.Float'>
>>> type(b)
<class '__main__.Float'>
>>> a += b
>>> type(a)
<type 'float'>

Now,  the type of a has silently changed.   It was a Float, a derived class with
all kinds of properties, and it became a float -- a plain vanilla number.

My understanding is that this is incorrect, and certainly unexpected.
If it *is* correct, it certainly deserves mention somewhere in the documentation.

It seems that   Float.__iadd__(a, b) should be called.
This defaults to float.__iadd__(a, b), which should increment the float
part of the object while leaving the rest intact.

A possible explanation for this problem is that float.__iadd__ is not actually
defined, and so it falls through to
a = float.__add__(a, b), which assigns a float to a.

This interpretation seems to be correct, as one can add a destructor to the Float class:

>>> class FloatD(float):
...     def __init__(self, v):
...             float.__init__(self, v)
...             self.x = 1
...     def __del__(self):
...             print 'Deleting FloatD class, losing x=', self.x
...
>>> a = FloatD(2.0)
>>> b = FloatD(3.0)
>>> a += b
Deleting FloatD class, losing x= 1
>>>

----------------------------------------------------------------------

Comment By: Josiah Carlson (josiahcarlson)
Date: 2007-01-16 09:40

Message:
Logged In: YES 
user_id=341410
Originator: NO

The current behavior is as designed.  Not a bug.  Suggested move to RFE or
close as "Not a bug".

There has been discussion on either the python-dev or python-3000 mailing
lists discussing how subclasses of builtin types (int, long, float, str,
unicode, list, tuple, ...) should behave when confronted with one of a set
of "standard" operators.  While there has been general "it would be nice"
if 'a + b' produced 'type(a)(a + b)' on certain occasions, this would
change the semantics of all such operations in a backwards incompatible
way (so has not been implemented).

If you want to guarantee such behavior (without writing all of the
__special__ methods) I would suggest that you instead create a __getattr__
method to automatically handle the coercion back into your subtype.

----------------------------------------------------------------------

Comment By: Georg Brandl (gbrandl)
Date: 2007-01-13 09:57

Message:
Logged In: YES 
user_id=849994
Originator: NO

You don't need augmented assign for that, just doing "a+b" will give you a
float too.

----------------------------------------------------------------------

Comment By: Jim Jewett (jimjjewett)
Date: 2007-01-12 13:26

Message:
Logged In: YES 
user_id=764593
Originator: NO

Python float objects are immutable and can be shared. 
Therefore, their values cannot be modified -- which is why it falls back
to not-in-place assignment.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1633630&group_id=5470


More information about the Python-bugs-list mailing list