fastest way to detect a user type

Steven D'Aprano steve at
Sun Feb 1 17:02:17 CET 2009

Robin Becker wrote:

> Steven D'Aprano wrote:
>> Paul Rubin wrote:
>>> Steven D'Aprano <steve at> writes:
>>>> First question is, why do you care that it's slower? The difference
>>>> between the fastest and slowest functions is 1.16-0.33 = 0.83
>>>> microsecond.
>>> That's a 71% speedup, pretty good if you ask me.
>> Don't you care that the code is demonstrably incorrect? The OP is
>> investigating options to use in Python 3, but the fastest method will
>> fail, because the "type is InstanceType" test will no longer work. (I
>> believe the fastest method, as given, is incorrect even in Python 2.x, as
>> it will accept ANY old-style class instead of just the relevant X or V
>> classes.)
> I'm not clear why this is true? Not all instances will have the __X__
> attribute or has something else changed in Python3?

The func0() test doesn't look for __X__.

> The original code was intended to be called with only a subset of all
> class instances being passed as argument; as currently written it was
> unsafe because an instance of an arbitrary old class would pass into
> branch 1. Of course it will still be unsafe as arbitrary instances end
> up in branch 3
> The intent is to firm up the set of cases being accepted in the first
> branch. The problem is that when all instances are new style then
> there's no easy check for the other acceptable arguments eg float,int,
> str etc, 

Of course there is.

isinstance(ob, (float, int)) 

is the easy, and correct, way to check if ob is a float or int.

> as I see it, the instances must be of a known class or have a 
> distinguishing attribute.

Are you sure you need to check for different types in the first place? Just
how polymorphic is your code, really? It's hard to judge because I don't
know what your code actually does.

> As for the timing, when I tried the effect of func1 on our unit tests I
> noticed that it slowed the whole test suite by 0.5%. 

An entire half a percent slower. Wow.

That's like one minute versus one minute and 0.3 second. Or one hour, versus
one hour and 18 seconds. I find it very difficult to get worked up over
such small differences. I think you're guilty of premature optimization:
wasting time and energy trying to speed up parts of the code that are
trivial. (Of course I could be wrong, but I doubt it.)

> Luckily func 3 
> style improved things by about 0.3% so that's what I'm going for.

I would call that the worst solution. Not only are you storing an attribute
which is completely redundant (instances already know what type they are,
you don't need to manually store a badge on them to mark them as an
instance of a class), but you're looking up this attribute only to
immediately throw away the value you get. The only excuse for this extra
redirection would be if it were significantly faster. But it isn't: you
said it yourself, 0.3% speed up. That's like 60 seconds versus 59.82


More information about the Python-list mailing list