Skip to content

Commit d0af36b

Browse files
authored
Introduce the "bare"/"explicitly typed" Final terminology (#2370)
1 parent 46f693a commit d0af36b

8 files changed

Lines changed: 48 additions & 33 deletions

File tree

‎docs/guides/libraries.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,10 @@ type annotation would be redundant.
568568
COLOR_FORMAT_RGB: Literal["rgb"] = "rgb"
569569
LATEST_VERSION: tuple[int, int] = (4, 5)
570570
571-
# Final variable with inferred type
571+
# Bare Final variable with inferred type
572572
ColorFormatRgb: Final = "rgb"
573573
574-
# Final variable with explicit type
574+
# Explicitly typed Final variable
575575
ColorFormatRgb: Final[Literal["rgb"]] = "rgb"
576576
LATEST_VERSION: Final[tuple[int, int]] = (4, 5)
577577

‎docs/guides/writing_stubs.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ still recommended to separately define known attributes.
349349
Constants
350350
---------
351351

352-
When the value of a constant is important, mark it as ``Final`` and assign it
353-
to its value.
352+
When the value of a constant is important, mark it as a :term:`bare Final` and
353+
assign it to its value.
354354

355355
Yes::
356356

‎docs/spec/dataclasses.rst‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,9 @@ This includes, but is not limited to, the following semantics:
526526
* ClassVar attributes are not considered dataclass fields and are
527527
`ignored by dataclass mechanisms <https://docs.python.org/3/library/dataclasses.html#class-variables>`_.
528528

529-
* A dataclass field may be annotated with ``Final[...]``. For example, ``x:
530-
Final[int]`` in a dataclass body specifies a dataclass field ``x``, which
529+
* A dataclass field may be annotated with an :term:`explicitly typed Final`
530+
:term:`type qualifier`. For example, ``x: Final[int]``
531+
in a dataclass body specifies a dataclass field ``x``, which
531532
will be initialized in the generated ``__init__`` and cannot be assigned to
532533
thereafter. A ``Final`` dataclass field initialized in the class body is not
533534
a class attribute unless explicitly annotated with ``ClassVar``. For example,

‎docs/spec/distributing.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ assignments::
105105
x = 0 # type: int
106106
x = ... # type: int
107107

108-
The :ref:`Literal shortcut using Final <literal-final-interactions>` should be
109-
supported::
108+
The :ref:`Literal shortcut using a bare Final <literal-final-interactions>`
109+
should be supported::
110110

111111
x: Final = 0 # type is Literal[0]
112112

‎docs/spec/glossary.rst‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ This section defines a few terms that may be used elsewhere in the specification
2727
``B``, respectively, such that ``B'`` is a subtype of ``A'``. See
2828
:ref:`type-system-concepts`.
2929

30+
bare ``Final``
31+
A :ref:`Final <uppercase-final>` :term:`type qualifier` without an
32+
explicit type, e.g. ``x: Final``.
33+
3034
closed
3135
A :ref:`TypedDict <typeddict>` type is closed if it may not contain any
3236
additional :term:`items <item>` beyond those specified in the TypedDict definition.
@@ -59,6 +63,10 @@ This section defines a few terms that may be used elsewhere in the specification
5963
also materializations of ``B``, and all materializations of ``B`` are
6064
also materializations of ``A``.
6165

66+
explicitly typed ``Final``
67+
A :ref:`Final <uppercase-final>` :term:`type qualifier` with an explicit
68+
type, e.g. ``x: Final[int]``.
69+
6270
extra items
6371
A :ref:`TypedDict <typeddict>` type with extra items may contain arbitrary
6472
additional key-value pairs beyond those specified in the TypedDict definition, but those

‎docs/spec/literal.rst‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,8 @@ involving Literal bools. For example, we can combine ``Literal[True]``,
504504
Interactions with Final
505505
"""""""""""""""""""""""
506506

507-
The ``Final`` qualifier can be used to declare that some variable or
508-
attribute cannot be reassigned::
507+
A :term:`bare Final` type qualifier can be used to declare that some variable
508+
or attribute cannot be reassigned::
509509

510510
foo: Final = 3
511511
foo = 4 # Error: 'foo' is declared to be Final
@@ -518,8 +518,8 @@ is valid to use in any context that expects a ``Literal[3]``::
518518

519519
expects_three(foo) # Type checks, since 'foo' is Final and equal to 3
520520

521-
The ``Final`` qualifier serves as a shorthand for declaring that a variable
522-
is *effectively Literal*.
521+
A :term:`bare Final` type qualifier serves as a shorthand for declaring that a
522+
variable is *effectively Literal*.
523523

524524
Type checkers are expected to
525525
support this shortcut. Specifically, given a variable or attribute assignment
@@ -530,7 +530,7 @@ any context that expects a ``Literal[value]``.
530530
Type checkers are not obligated to understand any other uses of Final. For
531531
example, whether or not the following program type checks is left unspecified::
532532

533-
# Note: The assignment does not exactly match the form 'var: Final = value'.
533+
# Note: Literal inference is unspecified for explicitly typed Final.
534534
bar1: Final[int] = 3
535535
expects_three(bar1) # May or may not be accepted by type checkers
536536

‎docs/spec/qualifiers.rst‎

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -81,30 +81,27 @@ variable or attribute should not be reassigned, redefined, or overridden.
8181
Syntax
8282
^^^^^^
8383

84-
``Final`` may be used in one of several forms:
84+
``Final`` may be used in one of two forms:
8585

86-
* With an explicit type, using the syntax ``Final[<type>]``. Example::
86+
* As an :term:`explicitly typed Final`, using the syntax ``Final[<type>]``.
87+
Example::
8788

8889
ID: Final[float] = 1
8990

90-
* With no type annotation. Example::
91+
In class bodies and stub files the right hand side can be omitted::
92+
93+
ID: Final[float]
94+
95+
* As a :term:`bare Final`, without a type argument. Example::
9196

9297
ID: Final = 1
9398

99+
Bare ``Final`` annotations must have an assigned value.
100+
94101
The typechecker should apply its usual type inference mechanisms to
95102
determine the type of ``ID`` (here, likely, ``int``). Note that unlike for
96103
generic classes this is *not* the same as ``Final[Any]``.
97104

98-
* In class bodies and stub files you can omit the right hand side and just write
99-
``ID: Final[float]``. If the right hand side is omitted, there must
100-
be an explicit type argument to ``Final``.
101-
102-
* Finally, as ``self.id: Final = 1`` (also optionally with a type in
103-
square brackets). This is allowed *only* in ``__init__`` methods, so
104-
that the final instance attribute is assigned only once when an
105-
instance is created.
106-
107-
108105
Semantics and examples
109106
^^^^^^^^^^^^^^^^^^^^^^
110107

@@ -156,8 +153,8 @@ be initialized in the ``__init__`` method (except in stub files)::
156153
self.x = 1 # Good
157154

158155
The generated ``__init__`` method of :doc:`dataclasses` qualifies for this
159-
requirement: a bare ``x: Final[int]`` is permitted in a dataclass body, because
160-
the generated ``__init__`` will initialize ``x``.
156+
requirement: an ``x: Final[int]`` without an initializer is permitted in a
157+
dataclass body, because the generated ``__init__`` will initialize ``x``.
161158

162159
Type checkers should infer a final attribute that is initialized in a class
163160
body as being a class variable, except in the case of :doc:`dataclasses`, where
@@ -167,6 +164,15 @@ necessary to create a final class variable with value ``3``. In
167164
non-dataclasses, combining ``ClassVar`` and ``Final`` is redundant, and type
168165
checkers may choose to warn or error on the redundancy.
169166

167+
``Final`` attributes can also be declared in ``__init__`` methods, as
168+
annotations on an assignment to an attribute on ``self``. This is allowed
169+
*only* in ``__init__``, not in any other method::
170+
171+
class ImmutableAttributes:
172+
def __init__(self) -> None:
173+
self.x: Final = 3
174+
self.y: Final[str] = "knight"
175+
170176
``Final`` may only be used in assignments or variable annotations. Using it in
171177
any other position is an error. In particular, ``Final`` can't be used in
172178
annotations for function arguments::
@@ -193,9 +199,9 @@ with ``Final`` to prevent mutating such values::
193199
z: Final = ('a', 'b') # Also works
194200

195201

196-
Type checkers should treat uses of a final name that was initialized
197-
with a literal as if it was replaced by the literal. For example, the
198-
following should be allowed::
202+
Type checkers should treat uses of names declared with a :term:`bare Final`
203+
that was initialized with a literal as if it was replaced by the literal. For
204+
example, the following should be allowed::
199205

200206
from typing import NamedTuple, Final
201207

‎docs/spec/typeddict.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,8 @@ certain items. For example, ``d['x'] = 1`` should generate a type check error
733733
if ``'x'`` is not a valid key for ``d`` (which is assumed to be a TypedDict
734734
type), unless ``d`` has mutable :term:`extra items` of a compatible type.
735735

736-
Type checkers should allow :ref:`final names <uppercase-final>` with
737-
string values to be used instead of string literals in operations on
736+
Type checkers should allow names declared with a :term:`bare Final` and a
737+
string value to be used instead of string literals in operations on
738738
TypedDict objects. For example, this is valid::
739739

740740
YEAR: Final = 'year'

0 commit comments

Comments
 (0)