On 10/21/21 1:17 AM, Steven D'Aprano wrote:
On Thu, Oct 21, 2021 at 04:48:28PM -0400, Larry Hastings wrote:
In Python, if you evaluate an undefined name, Python raises a
NameError. This is so consistent I'm willing to call it a "rule".
Various folks have proposed an exception to this "rule": evaluating an
undefined name in an PEP 649 delayed annotation wouldn't raise
NameError, instead evaluating to some yet-to-be-determined value
(ForwardRef, AnnotationName, etc). I don't think annotations are
special enough to "break the rules" in this way.
Can we have a code snippet illustrating that? I think this is what you
mean. Please correct me if I have anything wrong.
If I have this:
from typing import Any
def function(arg:Spam) -> Any: ...
then we have four sets of (actual or proposed) behaviour:
1. The original, current and standard behaviour is that Spam raises a
NameError at function definition time, just as it would in any other
context where the name Spam is undefined, e.g. `obj = Spam()`.
2. Under PEP 563 (string annotations), there is no NameError, as the
annotations stay as strings until you attempt to explicitly resolve them
using eval. Only then would it raise NameError.
3. Under PEP 649 (descriptor annotations), there is no NameError at
function definition time, as the code that resolves the name Spam (and
Any for that matter) is buried in a descriptor. It is only on inspecting
`function.__annotations__` at runtime that the code in the descriptor is
run and the name Spam will generate a NameError.
4. Guido would(?) like PEP 649 to be revised so that inspecting the
annotations at runtime would not generate a NameError. Since Spam is
unresolvable, some sort of proxy or ForwardRef (or maybe just a
string?) would have to be returned instead of raising.
Am I close?
Your description of the four behaviors is basically correct.
So if I have understood the options correctly, I like the idea of a
hybrid descriptor + stringy annotations solution.
- defer evaluation of the annotations using descriptors (PEP 649);
- on runtime evaluation, if a name does not resolve, stringify it (as
PEP 563 would have done implicitly);
- anyone who really wants to force a NameError can eval the string.
You might also be interested in my "Great Compromise" proposal from back
in April:
https://mail.python.org/archives/list/python-dev@python.org/thread/WUZGTGE43T7XV3EUGT6AN2N52OD3U7AE/
Naturally I'd prefer PEP 649 as written. The "compromise" I described
would have the same scoping limitations as stringized annotations, one
area where PEP 649 is a definite improvement.
Cheers,
//arry/
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/HEAXKK7U2YNGSV6AFVDG7XNIL34DE5TF/
Code of Conduct: http://python.org/psf/codeofconduct/