On Mon, Jan 11, 2021 at 5:57 PM Larry Hastings <larry@hastings.org> wrote:
On 1/11/21 5:05 PM, Greg Ewing wrote:
On 12/01/21 6:22 am, Larry Hastings wrote:
* The language will set __annotations__ to a dict if the object has
annotations, or None if it has no annotations.
That sounds inconvenient -- it means that any code referencing __annotations__ has to guard against the possibility of it being None.
It was a balancing act. Using an 64-byte empty dict per object with no defined annotations seems so wasteful. And anything short of an empty dict, you'd have to guard against. Current code already has to guard against "__annotations__ aren't set" anyway, so I figured the cost of migrating to checking a different condition would be small. And None is so cheap, and the guard is so easy:
if o.__annotations__:
But if things could fall through in the default case such that use in a `for` loop, it is nice as Guido pointed out. The other thing to keep in mind is we are talking about every module, class, and function getting 64 bytes ... which I bet isn't that much. I bet you save more memory running with -OO than what this will cost users in memory. And I know you were somewhat joking when you mentioned using sys.version_info, but since this would be behind a __future__ import it means the version check just means you then need to *potentially* worry about the semantic shift (until the change becomes permanent). It seems the changes are all still easy enough to have fallthrough and semantic checks that it won't be much of a problem. I think it really means people need to rely on typing.get_type_hints() more than they may be doing right now.
If we're changing things, I'm wondering if the best thing would be to introduce an annotations() function as the new best practice for getting an object's annotations. It would know how to handle all the type-specific pecularities, and could take care of things such as manufacturing an empty dict if the object doesn't have any annotations.
I guess I'm marginally against this, just because it seems like a needless change. We don't need the flexibility of a function with optional parameters and such, and with a data descriptor we can already put code behind __annotations__ (as I have already done). Plus, the function should probably cache its result--you wouldn't want code that called it ten times to generate ten fresh dicts, would you?--and already we're most of the way to what I proposed in PEP 649.
I also don't think introspection on annotations is common enough to warrant a built-in function; this stuff is meant for tools, not for the average developer to be dynamically playing with. As Guido pointed out, typing.get_type_hints() already covers this.