On 8/13/2019 8:53 PM, Steven D'Aprano wrote:
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?
It's especially expensive. More so in 3.7, and/or before PEP 560 (I
think that's the right one).
Wouldn't it be a once-off cost?
Yes, it would. But even that was too expensive.
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.
I realize there are ways to trick it, and probably even more so with
"virtual" subclassing. And you're right, they matter more here than in
dataclasses.
Eric
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at
https://mail.python.org/archives/list/python-ideas@python.org/message/SZPXGXINBKFEBNQEYZABDJUPODLGQ6AA/
Code of Conduct: http://python.org/psf/codeofconduct/