On 4 September 2016 at 21:32, Ivan Levkivskyi <levkivs...@gmail.com> wrote: > The first form still could be interpreted by type checkers > as annotation for value (a cast to more precise type): > > variable = cast(annotation, value) # visually also looks similar
I think a function based spelling needs to be discussed further, as it seems to me that at least some of the goals of the PEP could be met with a suitable definition of "cast" and "declare", with no syntactic changes to Python. Specifically, consider: def cast(value, annotation): return value def declare(annotation): return object() The idea here is that "cast" would be used as a hint to type checkers to annotate an *expression*, with the runtime semantic impact being exactly nil - the value just gets passed through unmodified. Annotated initialisations would then look like: from typing import cast primes = cast([], List[int]) class Starship: stats = cast({}, ClassVar[Dict[str, int]]) This preserves the relative annotation order of current type hints, where the item being annotated (parameter, function declaration, assignment statement) is on the left, and the annotation is on the right. In cases where the typechecker is able to infer a type for the expression, it may complain here when there's a mismatch between the type inference and the explicit declaration, so these would also be a form of type assertion. That leaves the case of declarations, where the aim is to provide a preemptive declaration that all assignments to a particular variable will include an implicit casting of the RHS. That would look like: from typing import declare captain = declare(str) Until it left the scope, or saw a new target declaration, a typechecker would then interpret future assignments to "captain" as if they had been written: captain = cast(RHS, str) With the above definition, this would have the runtime consequence of setting "captain" to a unique object() instance until the first assignment took place. Both that assignment, and the runtime overhead of evaluating the declaration, can be avoided by moving the declaration into otherwise dead code: if 0: captain = declare(str) Considering the goals and problems listed in the PEP, this would be sufficient to address many of them: * These are real expressions, and hence will be highlighted appropriately * declare() allows annotations of undefined variables (sort of) * These annotations will be in the AST, just as function arguments, rather than as custom nodes * In situations where normal comments and type comments are used together, it is difficult to distinguish them For the other goals, the function-based approach may not help: * For conditional branches, it's only arguably an improvement if 0: my_var = declare(Logger) if some_value: my_var = function() else: my_var = another_function() * Readability for typeshed might improve for module level and class level declarations, but functions would likely want the leading "if 0:" noise for performance reasons * Since the code generator remains uninvolved, this still wouldn't allow annotation access at runtime (unless typing implemented some sys._getframe() hacks in declare() and cast()) However, exploring this possibility still seems like a good idea to me, as it should allow many of the currently thorny semantic questions to be resolved, and a future syntax-only PEP for 3.7+ can just be about defining syntactic sugar for semantics that can (by then) already be expressed via appropriate initialisers. Regards, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com