Python Enhancement Proposal 824 Proposes Introduction of None-coalescing Operators to Language Specification
Python’s evolution as a language has frequently balanced the tension between readability and conciseness, often favoring explicit keywords over symbolic shorthand. However, a new formal proposal, PEP 824, authored by Marc Mueller and sponsored by Python creator Guido van Rossum, suggests a significant shift in how the language handles its most common sentinel value: None. The proposal introduces two new operators—the None-coalescing operator (??) and the None-coalescing assignment operator (??=)—designed to reduce boilerplate code and mitigate the risks associated with repetitive expression evaluation. Targeted for inclusion in Python 3.16, this proposal marks a renewed effort to address a decade-long debate regarding "null-aware" syntax in the Python ecosystem.
The core of the proposal centers on providing a more surgical tool for handling default values. Currently, Python developers often rely on the "or" operator to provide fallbacks, such as value = input_data or "default". While effective for truthy values, this pattern fails when a valid input is "falsy," such as the integer 0, an empty string, or an empty list. In these cases, the "or" operator skips the valid data and returns the default. To avoid this, developers are forced to write more verbose if value is not None checks. PEP 824 aims to eliminate this verbosity by introducing a dedicated operator that checks specifically for None, ignoring other falsy states.
Technical Mechanics of the Proposed Operators
The None-coalescing operator (??) is designed to evaluate the left-hand side of an expression and return its value if it is anything other than None. If the left-hand side evaluates to None, the right-hand side is then evaluated and returned. This follows a short-circuiting logic similar to the existing "and" and "or" operators. For example, in the expression result = a ?? b, the variable b is only evaluated if a is found to be None. This is particularly useful when the right-hand expression is "expensive," such as a database query or a complex calculation, as it ensures the operation only occurs when absolutely necessary.
The second part of the proposal, the None-coalescing assignment operator (??=), streamlines the process of updating variables. It performs a conditional assignment: if the variable on the left is None, the value on the right is assigned to it. This is intended to replace the common three-line pattern where a developer checks if a variable is None before assigning a default. By using a ??= b, the developer ensures that a is only overwritten if it currently holds no meaningful value.
From a technical implementation standpoint, the proposal suggests placing the precedence of the ?? operator lower than "or" but higher than conditional "if-else" expressions. This ensures that developers can combine truthiness checks with None-checks without creating ambiguous logic. For instance, x or y ?? 2 would be interpreted as (x or y) ?? 2. The proposal also outlines necessary changes to Python’s Abstract Syntax Tree (AST), introducing a new Coalesce operator within the boolop nodes, ensuring that the new syntax is deeply integrated into the language’s compilation pipeline.
A Decade of Deliberation: The Chronology of PEP 824
The journey toward None-coalescing operators in Python is not a new one. The conceptual predecessor, PEP 505, was first officially proposed in 2015. That proposal was significantly broader, encompassing not only coalescing operators but also None-aware member access (e.g., a?.b) and None-aware indexing (e.g., a?[0]). PEP 505 sparked intense debate within the Python Steering Council and the broader community, eventually being deferred as the community grappled with whether such "symbol-heavy" syntax aligned with the "Pythonic" philosophy of readability.
Between 2015 and 2024, the discussion moved to various forums, including Python’s Discourse and mailing lists. During this period, other modern programming languages—including TypeScript, JavaScript (ECMAScript), C#, Swift, Kotlin, and PHP—successfully implemented similar null-coalescing features. The ubiquity of these operators in other ecosystems began to influence Python developers, many of whom work in multi-language environments and found Python’s lack of these tools increasingly cumbersome.
In September 2026, Marc Mueller revived the core ideas of PEP 505 but opted for a more modular approach. By splitting the original proposal into PEP 824 (focusing on coalescing) and PEP 823 (focusing on access operators), the authors aim to allow the community to evaluate and adopt these features independently. This strategic decoupling is intended to lower the barrier for acceptance, addressing the specific "syntactic sugar" needs of the community without overwhelming the language with too many symbols at once.
Comparative Landscape: How Python Matches Global Standards
Python’s move toward None-coalescing operators brings it into alignment with the vast majority of modern high-level languages. In the world of web development, JavaScript and TypeScript introduced the ?? operator in ECMAScript 2020 to solve the exact same "falsy value" problem Python faces. In those languages, using || (the equivalent of Python’s or) often led to bugs when developers accidentally ignored 0 or false values.
C# has utilized the ?? operator since version 2.0, released in 2005, making it one of the earliest adopters of the pattern. Similarly, Apple’s Swift uses ?? for unwrapping optionals, and Kotlin uses the "Elvis operator" (?:) for the same purpose. The prevalence of this pattern across diverse paradigms—from the systems-adjacent C# to the UI-focused Swift—suggests that handling null/None values is a universal challenge in software engineering that transcends specific language philosophies.
By adopting PEP 824, Python acknowledges that while "explicit is better than implicit," the current requirement for explicit None-checks creates "noise" that can obscure the actual logic of a program. The proposal argues that ?? is not just a shortcut, but a clearer way to communicate intent to other developers.
Community Responses and Potential Objections
The proposal has met with a mix of enthusiastic support and principled caution. Proponents argue that the current verbosity of None-handling is a source of "mental load." When a developer sees x if x is not None else y, they must mentally parse the repetition of x and ensure that x does not have side effects that would trigger twice. With x ?? y, the intent is atomic and the execution is guaranteed to be safe.
However, a segment of the Python community remains wary of "symbolic bloat." A common objection is that None is not "special enough" to deserve its own dedicated operator. Some critics argue that if Python adds ?? for None, it might eventually be pressured to add similar operators for other sentinels or specific error types, leading to a language that looks more like "alphabet soup" than the clean, readable prose Python is known for.
Another point of contention involves the "proliferation of None." Some architectural purists believe that if it becomes easier to handle None, developers will be more likely to design functions that return None instead of raising exceptions or returning empty objects. They argue this could lead to "fragile" codebases where None values propagate through multiple layers of an application before eventually causing a failure. In response, PEP 824 supporters point out that None is already used extensively in the standard library and third-party packages like NumPy and Pandas; providing better tools to handle it is a pragmatic necessity, not an endorsement of poor design.
Technical Implications and Security Considerations
One of the more nuanced aspects of the proposal is the rejection of "atomicity" for the ??= operator. During discussions, some developers suggested that the None-coalescing assignment should be atomic to prevent race conditions in multi-threaded environments. However, the proposal clarifies that like other augmented assignments (such as +=), ??= will not be inherently thread-safe. If two threads check a variable simultaneously and both find it to be None, they may both attempt to assign a value. The proposal concludes that developers should continue to use existing synchronization primitives, like locks, for thread-sensitive operations.
On the security front, the proposal asserts that there are no new implications. Because the operators are essentially syntactic sugar for existing conditional logic, they do not introduce new vectors for exploitation. In fact, by reducing the need for repeated expression evaluation, they may indirectly prevent certain types of logic errors where a value changes between a check and an assignment.
Broader Impact on the Python Ecosystem
If adopted, PEP 824 will necessitate updates across the entire Python ecosystem, from IDEs and linters to educational materials. Tools like Mypy and Pyright will need to be updated to handle type inference for the new operators. For instance, if a is of type Optional[int] and b is an int, the result of a ?? b should be inferred as a non-optional int.
From an educational perspective, the proposal suggests that ?? should be taught alongside and and or as part of Python’s suite of conditional operators. The documentation will likely emphasize the distinction between "truthiness" (handled by or) and "existence" (handled by ??).
The long-term impact of PEP 824 could be a cleaner, more expressive Python. By removing the "boilerplate tax" on None-handling, the language allows developers to focus on high-level logic. Whether this proposal will finally break the decade-long stalemate on None-aware operators remains to be seen, but with the backing of Guido van Rossum and a clear, modular implementation plan, PEP 824 represents the most viable path forward for this long-requested feature. As Python 3.16 approaches its development cycle, the community’s focus will remain on whether these two small symbols can deliver a large-scale improvement to the developer experience.