On 1/16/21 8:41 AM, Nick Coghlan wrote:
Could you get the best of both worlds by making __annotations__ an auto-populating descriptor on "type", the way it is on functions?
Continue to add a non-empty annotations dict to the class dict eagerly, but only add the empty dict when "cls.__annotations__" is accessed.
I think that'll work though it's a little imprecise. Consider the best practice for getting class annotations, example here from Lib/dataclasses.py: cls_annotations = cls.__dict__.get('__annotations__', {}) What happens when that current best practice code meets your proposed "lazy-populate the empty dict" approach? * If a class has annotations set, cls.__dict__['__annotations__'] will be set, so the code works fine. * If a class doesn't have annotations set, then cls.__dict__['__annotations__'] won't be set yet. So people peering in cls.__dict__['__annotations__'] will get the right /answer/, that no annotations are set. But they'll see the wrong /specifics/: they'll think annotations are unset, when in fact it has an empty dict as its value. So the code will continue to work, even though it's arguably a little misguided. If anybody distinguished between "annotations are unset" and "annotations are set to an empty dict", that code would fail, but I expect nobody ever does that. Two notes about this idea. First, I think most people who use this best-practices code above use it for modules as well as classes. (They have two code paths: one for functions, the other for not-functions.) But everything I said above is true for both classes and modules. Second, I think this is only sensible if, at the same time, we make it illegal to delete cls.__annotations__. If we lazy-populate the empty dict, and a user deletes cls.__annotations__, and we don't remember some extra state, we'd just re-"lazy" create the empty dict the next time they asked for it. Which is actually what functions do, just lazy-repopulate the empty annotations dict every time, and I'm not keen to bring those semantics to classes and modules. Cheers, //arry/