[Python-ideas] isinstance(Decimal(), Real) -> False?

Oscar Benjamin oscar.j.benjamin at gmail.com
Wed Aug 28 14:48:30 CEST 2013


On 28 August 2013 13:06, Vernon D. Cole <vernondcole at gmail.com> wrote:
> Now, consider when I am processing the arguments for an SQL "execute"
> method. [*]  How do I prepare the values for the underlying db engine? I use
> a long list which includes lots of "elif isinstance(value, <some Python
> type>):"
>
> The code for "isinstance(value, Real)" is quite straight forward.
>
> The code for "isinstance(value, decimal.Decimal)" requires 18 lines of
> incredibly obscure Python.
>
> I really do need to be able to tell them apart.

Can you not just reverse the order of those two tests? i.e.:

elif isinstance(value, decimal.Decimal):
    # obscure decimal code
elif isinstance(value, Real):
    # code for real

or what about

elif isinstance(value, decimal.Decimal) and not isinstance(value, Real):
   # obscure decimal code

or even

elif isinstance(value, float):
   # code for float
elif isinstance(value, decimal.Decimal):
    # obscure decimal code

What other types are you hoping to catch by testing against
numbers.Real instead of float? What guarantees does the Real ABC give
you in this situation that Decimal does not (hence requiring all the
obscure code)?

BTW it's not a big deal for database code but for intensive numerical
code it's worth noting that testing against numbers.Real is
significantly slower than testing against float:

    $ py -3.3 -m timeit -s 'from numbers import Real' 'isinstance(1.0, Real)'
    1000000 loops, best of 3: 1.93 usec per loop
    $ py -3.3 -m timeit -s 'from numbers import Real' 'isinstance(1.0, float)'
    1000000 loops, best of 3: 0.217 usec per loop

You can use a tuple to speed it up for float:

    $ py -3.3 -m timeit -s 'from numbers import Real' 'isinstance(1.0,
(float, Real))'
    1000000 loops, best of 3: 0.277 usec per loop

Given that

    $ py -3.3 -m timeit -s 'a = 123.45; b=987.654' 'a+b'
    10000000 loops, best of 3: 0.0718 usec per loop

it seems that isinstance(x, float) is roughly the same as 4 arithmetic
operations and isinstance(x, Real) is about 40 arithmetic operations.


Oscar


More information about the Python-ideas mailing list