Skip to content

Commit 1317769

Browse files
authored
PEP 824: Expand 'How to Teach This' to a mini-tutorial (#5179)
Original by me; updates by ChatGPT and myself working together; reviewed by me and @cdce8p.
1 parent b5125a6 commit 1317769

1 file changed

Lines changed: 92 additions & 14 deletions

File tree

‎peps/pep-0824.rst‎

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -307,20 +307,92 @@ There are no new security implications from this proposal.
307307
How to Teach This
308308
=================
309309

310-
In a practical sense it might be helpful to think of the "``None``-coalescing"
311-
operator ``??`` as a special case for the conditional ``or``
312-
operator, with the caveat that ``??`` checks for ``is not None`` instead
313-
of truthiness. As such it makes sense to include ``??`` when teaching
314-
the other conditional operators ``and`` and ``or``.
315-
316-
The "``None``-coalescing assignment" operator ``??=`` can be best
317-
thought of as a conditional assignment operator. As it is closely
318-
related to ``??``, explaining these together would make sense.
319-
Though it looks related to binary assignment operators like ``+=``
320-
as well, it is worth pointing out the distinction between these.
321-
Since ``??=`` is a **conditional** assignment operator, the right-hand
322-
side will be skipped entirely in some case, while ``+=`` always
323-
evaluates both sides.
310+
Prerequisites
311+
-------------
312+
313+
Students should already know how the short-circuit operators ``and`` and
314+
``or`` work, and what counts as truthy and falsy values.
315+
316+
Basics
317+
------
318+
319+
The ``??`` operator is a short-circuit operator like ``and`` and ``or``
320+
that only checks whether its left argument is ``None``. The others check
321+
for truthiness or falsiness, and treat values like ``0``, ``""`` and ``[]``
322+
as falsy.
323+
324+
``a ?? b`` is equivalent to ``a if a is not None else b``, except that
325+
``a`` is only evaluated once. Similarly, ``a or b`` is equivalent to
326+
``a if a else b``, with ``a`` evaluated only once.
327+
328+
For example, ``d.get(key) ?? make_default()`` calls ``make_default()``
329+
only when the key is missing or its value is ``None``. By contrast,
330+
``d.get(key, make_default())`` always evaluates ``make_default()``, and
331+
still returns ``None`` when the key is present with a ``None`` value.
332+
333+
The ``??=`` operator is the conditional assignment operator derived from
334+
``??``. ``a ??= b`` has the same effect as ``a = a ?? b``, except that
335+
there is no assignment when ``a`` is not ``None``. Like augmented
336+
assignment, it evaluates the target only once. For example, in
337+
``a[index()] ??= b``, ``index()`` is called only once. The right-hand
338+
side is evaluated only when the target's value is ``None``.
339+
340+
Chaining
341+
--------
342+
343+
An expression like ``a ?? b ?? c ?? d`` evaluates its subexpressions
344+
(``a``, ``b``, etc.) from left to right until it finds a value that is
345+
not ``None`` or reaches the end. If all values are ``None``, the result
346+
is ``None``.
347+
348+
Like ``or``, ``??`` is associative: ``(a ?? b) ?? c`` has the same
349+
meaning as ``a ?? (b ?? c)``.
350+
351+
Operator precedence
352+
-------------------
353+
354+
The ``??`` operator has a lower precedence than ``or`` and ``and``.
355+
Thus, ``a or b ?? c`` means ``(a or b) ?? c``, and ``a ?? b and c``
356+
means ``a ?? (b and c)``. To get the opposite grouping, use
357+
``a or (b ?? c)`` or ``(a ?? b) and c``.
358+
359+
This precedence is a convention. For clarity, we recommend always adding
360+
parentheses when mixing ``??`` with ``and`` or ``or``.
361+
362+
When to use
363+
-----------
364+
365+
This is useful when you find yourself writing expressions like
366+
``a if a is not None else b`` a lot. It can also replace
367+
``a if a else b`` and ``a or b`` when a ``None`` check is intended:
368+
use ``a ?? b`` for either.
369+
370+
The ``??=`` operator is handy for providing defaults for arguments.
371+
For example:
372+
373+
.. code-block:: python
374+
375+
def add_default_user(users: list[User] | None = None) -> list[User]:
376+
if users is None:
377+
users = []
378+
users.append(create_default_user())
379+
return users
380+
381+
This can be compacted to:
382+
383+
.. code-block:: py824
384+
385+
def add_default_user(users: list[User] | None = None) -> list[User]:
386+
users ??= []
387+
users.append(create_default_user())
388+
return users
389+
390+
When not to use
391+
---------------
392+
393+
Do not use these operators when you also want to check for other falsy
394+
values. For example, ``name ?? "unknown"`` preserves an empty string,
395+
whereas ``name or "unknown"`` replaces ``""`` with ``"unknown"``.
324396

325397
Reading expressions out loud
326398
----------------------------
@@ -612,6 +684,12 @@ Footnotes
612684
(https://perldoc.perl.org/perlop#Assignment-Operators)
613685
614686
687+
Change History
688+
==============
689+
690+
* 20-Oct-2026: Turned `How to Teach This`_ into a mini-tutorial.
691+
692+
615693
Copyright
616694
=========
617695

0 commit comments

Comments
 (0)