This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author larry
Recipients Guido.van.Rossum, eric.smith, gvanrossum, larry
Date 2021-04-24.23:51:49
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1619308310.62.0.059162629675.issue43901@roundup.psfhosted.org>
In-reply-to
Content
> 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.
History
Date User Action Args
2021-04-24 23:51:50larrysetrecipients: + larry, gvanrossum, eric.smith, Guido.van.Rossum
2021-04-24 23:51:50larrysetmessageid: <1619308310.62.0.059162629675.issue43901@roundup.psfhosted.org>
2021-04-24 23:51:50larrylinkissue43901 messages
2021-04-24 23:51:49larrycreate