Numeric coercions

Joshua Landau joshua.landau.ws at gmail.com
Sun Jul 7 04:34:24 EDT 2013


On 7 July 2013 09:15, Vlastimil Brom <vlastimil.brom at gmail.com> wrote:
> 2013/7/7 Steven D'Aprano <steve+comp.lang.python at pearwood.info>:
>> I sometimes find myself needing to promote[1] arbitrary numbers
>> (Decimals, Fractions, ints) to floats. E.g. I might say:
>>
>> numbers = [float(num) for num in numbers]
>>
>> or if you prefer:
>>
>> numbers = map(float, numbers)
>>
>> The problem with this is that if a string somehow gets into the original
>> numbers, it will silently be converted to a float when I actually want a
>> TypeError. So I want something like this:
>>
>>...
>> --
>> Steven
>> --
> Hi,
> I guess, a naive approach like
>
> numbers = [float(num+0) for num in numbers]
>
> wouldn't satisfy the performance requirements, right?

%~> \python -m timeit -s "n = 123" "n"
10000000 loops, best of 3: 0.0467 usec per loop

%~> \python -m timeit -s "n = 123" "float(n)"
1000000 loops, best of 3: 0.483 usec per loop

%~> \python -m timeit -s "n = 123" "n+0"
10000000 loops, best of 3: 0.0991 usec per loop

%~> \python -m timeit -s "n = 123" "float(n+0)"
1000000 loops, best of 3: 0.537 usec per loop


# And with more local lookup
%~> \python -m timeit -s "n = 123; ffloat=float" "ffloat(n)"
1000000 loops, best of 3: 0.424 usec per loop

%~> \python -m timeit -s "n = 123; ffloat=float" "ffloat(n+0)"
1000000 loops, best of 3: 0.483 usec per loop


"+0" takes only a small fraction of the time of "float" (about 25% at
worst), so I don't think that's too big a deal. My version of
safe_float much closer to that of float (only about 2% relative
overhead) but I'd say
it's also arguably more correct -- any value which is coercible to a
float has a ".__float__" method but not all numeric types are addable
to others:

>>> Decimal("0") + 0.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

It's conceivable that a numeric type could refuse to add to integers,
although very unlikely. The only reason Decimal refuses to add to
floats, AFAIK, is precision.



More information about the Python-list mailing list