Movatterモバイル変換
[0]ホーム
[Python-Dev] PEP 563: Postponed Evaluation of Annotations
Nick Coghlanncoghlan at gmail.com
Sat Nov 4 21:32:13 EDT 2017
On 5 November 2017 at 02:42, Guido van Rossum <guido at python.org> wrote:> I'm very worried about trying to come up with a robust implementation of> this in under 12 weeks. By contrast, the stringification that Łukasz is> proposing feels eminently doable.I'm far from confident about that, as the string proposal inherentlybreaks runtime type annotation evaluation for nested function andclass definitions, since those lose access to nonlocal variablereferences (since the compiler isn't involved in their name resolutionany more).https://www.python.org/dev/peps/pep-0563/#resolving-type-hints-at-runtimeis essentially defining a completely new type annotation specificscheme for name resolution, and takes us back to a Python 1.x era"locals and globals only" approach with no support for closurevariables.Consider this example from the PEP: def generate(): A = Optional[int] class C: field: A = 1 def method(self, arg: A) -> None: ... return C X = generate()The PEP's current attitude towards this is "Yes, it will break, butthat's OK, because it doesn't matter for the type annotation use case,since static analysers will still understand it". Adopting such acavalier approach towards backwards compatibility with behaviour thathas been supported since Python 3.0 *isn't OK*, since it would mean wewere taking the step from "type annotations are the primary use case"to "Other use cases for function annotations are no longer supported".The only workaround I can see for that breakage is that instead ofusing strings, we could instead define a new "thunk" type thatconsists of two things:1. A code object to be run with eval()2. A dictionary mapping from variable names to closure cells (or Nonefor not yet resolved references to globals and builtins)Correctly evaluating the code object in its original context wouldthen be possible by reading the "cell_contents" attributes of thecells stored in the mapping and injecting them into the globalsnamespace used to run the code.This would actually be a pretty cool new primitive to have available(since it also leaves the consuming code free to *ignore* the closurecells, which is what you'd want for use cases like callback functionswith implicitly named parameters), and retains the current eagercompilation behaviour (so we'd be storing compiled code objects asconstants instead of strings).If PEP 563 were updated to handle closure references properly using ascheme like the one above, I'd be far more supportive of the proposal.Alternatively, in a lambda based proposal that compiled code like theabove as equivalent to the following code today: def generate(): A = Optional[int] class C: field: A = 1 def method(self, arg: (lambda: A)) -> None: ... return C X = generate()Then everything's automatically fine, since the compiler wouldcorrectly resolve the nonlocal reference to A and inject theappropriate closure references.In such a lambda based implementation, the *only* tricky case is thisone, where the typevar is declared at class scope: class C: A = Optional[int] field: A = 1 def method(self, arg: A) -> None: ...Now, even without the introduction of the IndirectAttributeCellconcept, this is amenable to a pretty simple workaround: A = Optional[int] class C: field: A = 1 def method(self, arg: A) -> None: ... C.A = A del ABut I genuinely can't see how breaking annotation evaluation at classscope can be seen as a deal-breaker for the implicit lambda basedapproach without breaking annotation evaluation for nested functionsalso being seen as a deal-breaker for the string based approach.Either way, there are going to be changes needed to the compiler inorder for it to still generate suitable references at compile time -the only question would then be whether they're existing cells storedin a new construct (a thunk to be executed with eval rather than via aregular function call), or a new kind of cell stored on a regularfunction object (implicit access to class attributes from implicitlydefined scopes in the class body).Cheers,Nick.-- Nick Coghlan |ncoghlan at gmail.com | Brisbane, Australia
More information about the Python-Devmailing list
[8]ページ先頭