When I had been studying the documentation for the typing module, I found this:
To mark a function or a class as final we do this:
class Base:
@final
def final_method(): ...
@final
class FinalClass: ...
but when we want to mark a variable as final, we do this:
MAX_SIZE: Final = 9000
class Connection:
TIMEOUT: Final[int] = 10
So, I was wondering: what if we could decorate a variable too?
@final
MAX_SIZE = 9000
class Connection:
@final
TIMEOUT: int = 10
There are also other uses for:
class Point2D(TypedDict):
x: int
y: int
@not_required
label: str
class Point3D(TypedDict, total=False):
@required
x: int
@required
y: int
label: str
@annotated(ValueRange(-10, 5))
SliderA: int = 0
@annotated(ValueRange(-20, 3))
SliderB: int = -10
I’m curious about what you think of it. Especially if you have found other use for it outside of the typing module
You can already write v = dec(9). The point of decorator syntax is that class and def statements don’t have a clear value for the decorator to be applied to before the statement is processed. Assignment statements do.
I see the final decorator as a fix to the problem that you can’t annotate a function or class name before “assignment”, not something to expand into other use cases. For example, I have an open issue for mypy to accept code like:
foo: Final[Callable[[int], int]]
def foo(x):
...
(True, this adds a redundant refernce to foo, but some callable types are complicated enough that it would be nice to capture them in a single alias rather that distributing them among the parameters and return type explicitly.)
Yeah, this couldn’t ever work. The point of names (variables) is that they give a name to an object. If they were objects, then they’d have to be able to have their own names (recursively, even). But x = y already means that x becomes a name for the object y is naming, not for the name y itself.