This is a working implementation of final access qualifier briefly discussed at PyCon typing meeting. Final names/attributes can be used to have more static guarantees about semantics of some code and can be used by other tools like mypyc for optimizations.
We can play with this implementation before starting to write an actual PEP.
The basic idea is simple: once declared as final, a name/attribute can't be re-assigned, overridden, or redefined in any other way. For example:
from typing import Final NO: Final = 0 YES: Final = 255 class BaseEngine: RATE: Final[float] = 3000 YES = 1 # Error! class Engine(BaseEngine): RATE = 9000 # Also an error!
For more use cases, examples, and specification, see the docs patch.
Here are some comments on decisions made:
...and implementation internals:
The PR is open for questions, suggestions, and comments.
This is super cool!
Just two comments -- first, it might be nice if there were some tests + docs about Final and control flow. For example, the following program typechecks without an error:
[case testFinalControlFlow] from typing import Final for val in [1, 2, 3]: x: Final = val [builtins fixtures/list.pyi]
I found this a bit surprising since we are rebinding x several times/tools like mypyc can no longer assume that 'x' will have the same value within the loop. But then again, maybe this is ok? I think i'd be sort of hard to accidentally do something weird here, and any weirdness that does happen will be localized since x will be actually final after the loop is over...
Not sure, but either way, some clarification might be nice (unless you were planning on doing this in a different PR).
Second, I expect that this proposal will be rejected immediately for being too unpythonic + too messy to implemented, but I figure I might as well get it out of the way... How do we feel about adding a flag to mypy that makes all variables and attributes Final by default?
I would actually prohibit
In addition, I just noticed that I forgot about in-place assignments, will fix this soon.
I am not sure I understand this comment. Rejected immediately by whom? There were no objections during PyCon typing meeting, moreover many people liked the idea.
Same story here, sorry :-) Do you want to say that the implementation in this PR is messy?
I am not sure there is any existing Python program larger than 1k lines that will type-check with such flag. Plus we already have dozens of flags. So I am against this unless people will ask often for this.
Ah, I meant to say that I expected my proposal to add a flag to make final always-on by default would be rejected immediately by you.
(Which is what just happened -- but it was worth a shot
JukkaL left a comment
Thanks for writing so many test cases! This is a solid set of test cases. I only came up with a few additional scenarios.
This is almost concludes my review. I'll do another light pass next week (I don't expect anything major).
This pull request is a follow-up to python#6763: it renames some parameter names and variables that got missed up above. One interesting side-note: it seems like 'Var' notes also contain a `final_value` field that does almost the same thing as this `last_known_value` field, but is ultimately unrelated: it was introduced back in python#5522. I decided to leave this field alone. (I discovered this while updating mypyc and discovered (to my surprise) that nothing broke.)
This pull request is a follow-up to #6763: it renames some parameter names and variables that got missed up above. One interesting side-note: it seems like 'Var' notes also contain a `final_value` field that does almost the same thing as this `last_known_value` field, but is ultimately unrelated: it was introduced back in #5522. I decided to leave this field alone. (I discovered this while updating mypyc and discovered (to my surprise) that nothing broke.)
From python official documentation for Python3.7, I don't see