Larry Hastings <[email protected]> added the comment:
> Functions don't store __annotations__ in their __dict__, it is a
> separate slot named func_annotations (see funcobject.c). I guess
> that's because the __dict__ is purely for user-defined function
> attributes.
I brought up functions because I'm now proposing to make classes and modules
behave more like functions in this one way, that they too will now lazy-create
an empty annotations dict every time. But yes, function objects don't store
__annotations__ in their __dict__, and best practices for 3.9 and before was to
use fn.__annotations__ or getattr() when getting the annotations from a
function object, and 3.10 will not change that best practice.
I don't know specifically why the implementor made that design choice, but I
might have done that too. Most function objects don't have a __dict__ so this
is almost always cheaper overall. And recreating the dict seems harmless.
(Just to round the bases on this topic: I don't think you should be permitted
to delete __annotations__, like most other metadata items on functions /
classes / modules. But I don't propose to change that for 3.10.)
> So if you look in __dict__ it will be like it's still Python 3.9,
> but if you're using the attribute (the recommended approach for code
> that only cares about 3.10) it'll be as if it always existed. Sounds
> pretty compatible to me.
Yes, exactly. That was the thing I finally figured out this afternoon. Sorry
for being a slow learner.
Again, this approach will change the semantics around deleting annotations on
class and module objects. Deleting them won't be permanent--if you delete one,
then ask for it, a fresh one will be created. But that seems harmless.
> So, honestly I don't understand what your concern with the lazy
> approach is. Was your design based on having a bit in the
> class/module object (outside its __dict__) saying "I already
> lazily created one"? Or am I missing something?
My concern is that always lazy-creating on demand will change user-visible
behavior. Consider this code:
class C:
a:int=3
del C.__annotations__
print(C.__annotations__)
In 3.9, that throws an AttributeError, because C no longer has an
'__annotations__' attribute. If I change Python 3.10 so that classes and
modules *always* lazy-create __annotations__ if they don't have them, then this
code will succeed and print an empty dict.
That's a user-visible change, and I was hoping to avoid those entirely. Is it
a breaking change? I doubt it. Is it an important change? It doesn't seem
like it. I bring it up just in the interests of considering every angle. But
I don't think this is important at all, and I think always lazy-creating
annotations dicts on classes and modules is the right approach.
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue43901>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com