Larry Hastings <la...@hastings.org> 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 <rep...@bugs.python.org>
<https://bugs.python.org/issue43901>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to