
On Tue, Aug 13, 2019 at 06:01:27PM -0400, Eric V. Smith wrote:
dataclasses does something similar: it wants to know if something is a typing.ClassVar, but it doesn't want to import typing to find out.
Why not? Is importing typing especially expensive or a bottleneck? Wouldn't it be a once-off cost?
So it has:
typing = sys.modules.get('typing') if typing: if (_is_classvar(a_type, typing) or (isinstance(f.type, str) and _is_type(f.type, cls, typing, typing.ClassVar, _is_classvar))):
If typing hasn't been imported, it knows that a_type can't be typing.ClassVar.
That's very clever, but alas it's not clever enough because its false. Or rather, it's false in general. ClassVar is magic, it can't be used with isinstance() or issubclass(), so I won't argue about the above snippet. I don't understand it well enough to argue its correctness. But for regular classes like Decimal, this clever trick doesn't always work. Here's an example: py> import decimal py> x = decimal.Decimal() py> del decimal py> del sys.modules['decimal'] At this point, we have a Decimal instance, but no "decimal" in the module cache. Your test for whether x is a Decimal will wrongly deny x is a Decimal: # the wrong way to do it py> _decimal = sys.modules.get('decimal') py> isinstance(x, _decimal.Decimal) if _decimal else False False but if we're a bit less clever, we get the truth: py> import decimal py> isinstance(x, decimal.Decimal) True You can't rely on the presence of 'decimal' in the module cache as a proxy for whether or not x might be a Decimal instance. -- Steven