Skip to content

Commit 0cb92cb

Browse files
committed
Add TYPE_CHECKING, not __type_checking__.
1 parent e915074 commit 0cb92cb

File tree

1 file changed

+43
-39
lines changed

1 file changed

+43
-39
lines changed

peps/pep-0781.rst

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PEP: 781
2-
Title: Adding __type_checking__ constant
2+
Title: Make ``TYPE_CHECKING`` builtin
33
Author: Inada Naoki <songofacandy@gmail.com>
44
Discussions-To: https://discuss.python.org/t/85728
55
Status: Draft
@@ -14,12 +14,11 @@ Post-History: `11-Jan-2025 <https://discuss.python.org/t/76766>`__,
1414
Abstract
1515
========
1616

17-
This PEP proposes adding a new keyword, :data:`!__type_checking__`, to improve
17+
This PEP proposes adding a new builtin, :data:`!TYPE_CHECKING`, to improve
1818
the experience of writing Python code with type annotations. It is evaluated
1919
as ``True`` when the code is being analyzed by a static type checker, and as
2020
``False`` during normal runtime execution. Unlike :data:`typing.TYPE_CHECKING`,
21-
which this keyword replaces, it does not require an import statement, and
22-
creates the opportunity for compiler optimizations, such as smaller bytecode.
21+
which this keyword replaces, it does not require an import statement.
2322

2423

2524
Motivation
@@ -30,7 +29,7 @@ widespread adoption. A challenge with fully-annotated code is that many
3029
more imports are required in order to bring the relevant name into scope,
3130
potentially causing import cycles without careful design. This has been
3231
recognized by :pep:`563` and later :pep:`649`, which introduce two different
33-
mechanisms for deferred evaluation of type annotations. As PEP 563 notes,
32+
mechanisms for deferred evaluation of type annotations. As :pep:`563` notes,
3433
"type hints are ... not computationally free". The :data:`typing.TYPE_CHECKING`
3534
constant was thus introduced__, initially to aid in breaking cyclic imports.
3635

@@ -51,62 +50,67 @@ third-party tools in the ecosystem to standardize on a single behavior
5150
with guaranteed semantics, as for example some static type checkers currently
5251
do not permit local constants, only recognizing ``typing.TYPE_CHECKING``.
5352

54-
Furthermore, this allows compilers to eliminate type-checking-only code at
55-
compile time, as the constant is guaranteed to be ``False`` and cannot be
56-
reassigned. This reduces bytecode size and memory usage, and would help with
57-
writing type-annotated code for memory-constrained environments such as WASM
58-
or MicroPython.
5953

54+
Specification
55+
=============
6056

61-
Rationale
62-
=========
57+
``TYPE_CHECKING`` is a built-in constant and its value is ``False``.
58+
Unlike ``True``, ``False``, ``None``, and ``__debug__``, ``TYPE_CHECKING`` is
59+
not a real constant; assigning to it will not raise a ``SyntaxError``.
6360

64-
Using Keyword
65-
-------------
61+
Static type checkers must treat ``TYPE_CHECKING`` as ``True``, similar to
62+
:data:`typing.TYPE_CHECKING`.
6663

67-
Avoiding the addition of a new :ref:`keyword <python:keywords>`
68-
(like :data:`__debug__`) would be attractive because more keywords means
69-
a more complex language.
64+
If this PEP is accepted, the new ``TYPE_CHECKING`` constant will be
65+
the preferred approach, instead of the existing ``typing.TYPE_CHECKING``.
66+
However, ``typing.TYPE_CHECKING`` will not be deprecated in the foreseeable
67+
future.
7068

71-
However, adding a constant without a keyword (like :data:`__debug__`) requires
72-
special handling in both the compiler and runtime.
7369

74-
By implementing ``__type_checking__`` the same way as ``False``, we avoid the
75-
need for the special handling.
76-
Therefore, making it a keyword is the simpler approach.
70+
Backwards Compatibility
71+
=======================
7772

73+
Since ``TYPE_CHECKING`` doesn't prohibit assignment, existing code using
74+
``TYPE_CHECKING`` will continue to work.
7875

79-
Specification
80-
=============
76+
.. code-block:: python
8177
82-
``__type_checking__`` is a :ref:`keyword <python:keywords>` and its value is
83-
``False``.
84-
It can be used in the same way as ``False``, except it cannot be used as
85-
a matching pattern.
78+
# These code will work as before
79+
TYPE_CHECKING = False
80+
from typing import TYPE_CHECKING
8681
87-
Static type checkers must treat ``__type_checking__`` as ``True``,
88-
similar to :data:`typing.TYPE_CHECKING`.
8982
90-
If this PEP is accepted, ``__type_checking__`` will be the preferred approach,
91-
instead of ``typing.TYPE_CHECKING``. However, ``typing.TYPE_CHECKING`` will not
92-
be deprecated.
93-
Instead, it will be implemented as ``TYPE_CHECKING = __type_checking__``,
94-
allowing future type checkers to focus on only handling ``__type_checking__``.
83+
User can remove the assingment to ``TYPE_CHECKING`` after they stop using
84+
Python before 3.14.
9585

9686

9787
How to Teach This
9888
=================
9989

100-
* Use ``__type_checking__`` for skipping type-checking code at runtime.
101-
* Use :data:`typing.TYPE_CHECKING` to support Python versions before 3.14.
90+
* Use ``if TYPE_CHECKING:`` for skipping type-checking code at runtime.
91+
* Use ``from typing import TYPE_CHECKING`` to support Python versions before 3.14.
10292
* Workarounds like ``TYPE_CHECKING = False`` or ``if False: # TYPE_CHECKING``
103-
are not recommended since Python 3.14.
93+
are continued to work, but not recommended.
10494

10595

10696
Reference Implementation
10797
========================
10898

109-
* `python/cpython#131641 <https://github.com/python/cpython/pull/131641>`__
99+
* `python/cpython#131793 <https://github.com/python/cpython/pull/131793>`__
100+
101+
102+
Rejected Ideas
103+
==============
104+
105+
Eliminate type-checking-only Code
106+
---------------------------------
107+
108+
It is considered to add real constant named ``__type_checking__``
109+
to eliminate type-checking-only code at compile time.
110+
111+
However, adding real constant to language increase complexity of the language.
112+
Benefit from eliminating type-checking-only code is estimated to be not enough
113+
to justify the complexity.
110114

111115

112116
Copyright

0 commit comments

Comments
 (0)