subclassing float (or not)

Thomas Heller theller at python.net
Tue Feb 26 15:47:21 EST 2002


"Steven Majewski" <sdm7g at virginia.edu> wrote in message news:mailman.1014672051.7833.python-list at python.org...
>
> On Fri, 22 Feb 2002, Sean 'Shaleh' Perry wrote:
>
> >
> > On 22-Feb-2002 Thomas Heller wrote:
> > > I'm currently porting my own rewrite of Konrad Hinsen's PhysicalValue
> > > module to Python 2.2.
> > > Basically a PhysicalValue instance is a float conbined with a unit.
> > > Should I subclass float or should I not? What would I gain by doing
> > > this (except maybe some memory savings when I use __slots__)?
> > >
> >
> > Generally when you subclass you are saying "I am a special type of foo" where
> > foo is your parent.  I think in this instance it would make more sense to make
> > a new class which contains a float and a unit.  Give it methods so it acts how
> > you expect.
> >
>
> Except that how he expects it to act is exactly like a float except for
> carrying and propagating a little extra bit of state at each operation.
>
> Sounds like a good application for subclassing floats to me!
That's also what I thought first.
>
> You can do it (and could have always done it) with a container class,
That's what I was doing until now.
> but there are always holes where you need the operation to be
> coerced on the classes value and not the class itself. In some
> cases that still may be what you really want (because you also want
> to coerce the result to my_float rather than float), but at least
> if you miss something, a subclassed float will do something closer
> to the right thing.
>
> An example of what I mean is 'sqrt(MyFloat)' -- if MyFloat is a
> class that contains a float and has methods for __add__, __mul__,etc.
> sqrt(MyFloat) will raise an exception if passed a container class --
> you need to call 'sqrt(MyFloat.value)' , while:
>
> >>> class F(float):
> ...     pass
> ...
> >>> from math import *
> >>> sqrt( F(1.0))
> 1.0
>
> Will return a normal float where you may really want a custom F instance.
> ( Which is the better way to go wrong here may vary. )
>
> Two other float-like classes that I've had use for that are easier to
> do now with float subclasses:
>
> Values that carry and propagate standard errors or standard deviations
> with them.
>
> Values that carry an "audit trail" ( for taking chained ratios of
> experimental measures and trying to track down the inconsistent
> data. )

It seems you always end up with implementing something like

class F(float):
  # float subclass
  def __mul__(self, other):
    return F(float(self) * other, ...)

or

class F:
  # container class with a float instance variable
  def __mul__(self, other):
    return F(self.float * other, ...)

The only *real* difference seems that you can pass float
subclass instances to round(), log(), and these kind of functions.
As you already noted, normally they return the wrong results ;-(

Thomas





More information about the Python-list mailing list