On Thu, Sep 05, 2019 at 07:15:27PM +1000, Chris Angelico wrote:
Hang on hang on.... what's this situation where you're checking types of a zillion objects?
An earlier version of the statistics module used lots of isinstance checks in order to support arbitrary numeric types, and was a lot slower. The current version avoids most of those at the cost of being a lot less clear and elegant, but it improved performance somewhat. On my PC, an isinstance check against a single concrete type (not an ABC) is about three times as expensive as a float arithmetic operation, so in a tight loop it may not be an insignificant cost.
I think there's a bigger problem there than whether isinstance(x, int|str) is slower than isinstance(x, (int,str)) ! Even if this change DOES have a measurable impact on the time to do those checks, it only applies to unions, and if that's a notable proportion of your total run time, maybe there's a better way to architect this.
Maybe... but in my experience, only at the cost of writing quite ugly code. But having said all that, I'm not sure that we should be rejecting this proposal on the basis of performance when we haven't got any working code to measure performance of :) isinstance is a wrapper around PyObject_IsInstance(obj, class_or_tuple), and if I'm reading the C code correctly, PyObject_IsInstance is roughly equivalent to this Python pseudo-code: # Except in C, not Python def isinstance(obj, class_or_tuple): if type(class_or_tuple) is tuple: for C in class_or_tuple: if isinstance(obj, C): return True else: ... If Union is a built-in, we could have something like this: def isinstance(obj, class_or_tuple): if type(class_or_tuple) is Union: class_or_tuple = class_or_tuple.__union_params__ # followed by the same code as above typing.Union already defines .__union_params__ which returns a tuple of the classes used to construct the union, so in principle at least, there need be no significant performance hit from supporting Unions. -- Steven