5 ms·
Understanding the basic syntax for assignment isn’t a high bar to clear. While it’s maybe not ideal to use colons for both the “assignment-like” separator betwe
by goodside 8y ago
Understanding the basic syntax for assignment isn’t a high bar to clear. While it’s maybe not ideal to use colons for both the “assignment-like” separator between keys and values inside dictionaries and the annotation of types, introducing any new syntax features into a language that’s been around for decades is never without compromise. Colons are also used at the end of block statements and in index ranges and nobody complains.
In this case you hit the most benign sort of change: Code that was previously syntactically invalid is now syntactically valid but has silly semantics. There’s never going to be a way to avoid this with full generality, and your code never worked — type annotations just delayed your runtime error by one line.
When annotations were introduced in 3.4, there was no requirement they be used to annotate types instead of something else, so any valid Python expression is allowed syntactically. In 3.6 the use of annotations for anything other than types was provisionally deprecated, and in 3.7 is fully deprecated. In 3.8, non-type usage will be disallowed as a TypeError, and the only allowable non-type annotations will be strings, (which will be interpreted as bare identifiers for backward compatibility with pre-3.7 code that uses them as forward references). At this point your code will revert to raising an exception on exactly the same line it used to.
- masklinn 8y agoThe problem is not understanding, it's fat-fingering (especially when dict literals and dict comps use `:`). > type annotations just delayed your runtime error by one line. Or it introduces a subtle bug because this was intended as a reassignment or somesuch.
- goodside 8y agoThe real problem, as others point out, is not using a linter to catch errors before runtime. Mypy flags this problem through static analysis. You’re right I’m being uncharitable by saying “understanding”. I’m annoyed he bothered writing an accusatory blog post about this aspect of the language without mentioning any of the alternative syntax proposals helpfully discussed in the PEP, or exploring why annotations work this way. The designers have been very transparent and conservative in considering different ways of doing it, and the OP doesn’t offer any ideas for improving the interpreter, or note that the behavior he’s complaining about will be fixed in 3.8.
- lukeschlather 8y ago> Mypy flags this problem through static analysis. The problem is that there's not really such a thing as static analysis in python. For example, if I wrap it in a function like this, mypy doesn't complain at all. def blah(): ages = {} ages['John']: 42 print(ages['John']) return ages
- goodside 8y agoMypy intentionally does not check annotations inside untyped `def` statements. This is a feature meant to make it easier to gradually introduce types in code that wasn't intended to be typechecked. If you call mypy with the flag `--check-untyped-defs` or just annotate the function with anything at all, you will see mypy checks the inside of the function: from typing import Any def blah() -> Any: ... I'm not sure what you mean by "there's not really such a thing as static analysis" in Python -- that's exactly what Mypy does.
- lukeschlather 8y agoCool, I knew I had to be missing something. You're right of course.
- maxander 8y agoThere is a way to avoid this kind of problem; have sufficiently complicated syntax that most random permutations caused by "fat-fingering" are incorrect. Python's problem is that the syntax is so minimalist, and the semantics so rich, that any random typo is liable to do something. For what it's worth, I think Python's approach here is the right one (at least, for Python.) As others have noted, the common answer to this among Python users is to just use a linter to catch these kinds of issues, although I find that unsatisfying- linters can't catch everything, and they require you to have your stuff together well enough to use them (e.g., you can't be a student who is already overwhelmed with the bare necessary stack.) There are things that seem like they could be done to alleviate these kinds of problems within the language itself; most obviously, for the particular problem in the OP, a variable annotation expression could require the right-hand to be a type expression. It's not clear to me why these kinds of moves aren't taken.
- goodside 8y ago> a variable annotation expression could require the right-hand to be a type expression. It's not clear to me why these kinds of moves aren't taken Because when annotations were introduced in PEP 3107 they were not meant exclusively for type hinting. We're in a period now where non-type usage is deprecated but allowed for compatibility with old code. In 3.8 a non-type evaluation of the RHS will be disallowed.