Free Python reference · JavaScript timeline
Python 3.9: Convenient collections and exact text removal
Merge dictionaries with explicit precedence, annotate built-in collections, and remove a whole prefix or suffix without strip confusion.
Released · Editorial review October 25, 2026
Introduced in Python 3.9 · Language behavior
Dictionary union with |
left | right builds a new dictionary containing both mappings' entries. When a key exists in both, the right-hand value wins. This makes configuration layers readable: defaults on the left, overrides on the right.
The originals are preserved by |. The related |= updates the left dictionary in place. Neither operation recursively merges nested dictionaries; a conflicting nested value is replaced as a whole.
The example merges scalar options and prints the original default as evidence that the non-mutating form did not change it.
Earlier approach
settings = dict(defaults) settings.update(overrides)
Context fragment; read it with the example below.
Worked example
Minimum Python 3.9
defaults = {"theme": "light", "size": 12} overrides = {"size": 16} settings = defaults | overrides print(settings) print(defaults["size"])
Expected output
{'theme': 'light', 'size': 16}
12
Example checked with CPython 3.14.8, CPython 3.15.0, Pyodide Python 3.13.2.
Common mistake
Reversing the operands changes which conflicting value wins. A shallow merge does not combine nested configuration fields.
Try it yourself
Add a new key to overrides, then compare defaults | overrides with overrides | defaults.
Read more: Python 3.9 release notes · PEP 584
Introduced in Python 3.9 · Typing
Type hints with list[str] and dict[str, int]
Built-in collections can be parameterized directly in type expressions. Write list[str] rather than importing List solely to describe a list of strings. This works naturally for nested structures such as dict[str, list[int]].
The annotation documents element types for tools and readers. It does not cause Python to inspect every element at runtime. Function behavior is still determined by its implementation.
Use isinstance(value, list) for a basic runtime container check. A parameterized type such as list[str] is not an element-validation rule that you can pass to isinstance.
Earlier approach
from typing import List def total(scores: List[int]) -> int: return sum(scores)
Context fragment; read it with the example below.
Worked example
Minimum Python 3.9
def total(scores: list[int]) -> int: return sum(scores) print(total([2, 4, 6])) try: isinstance(["Ada"], list[str]) except TypeError: print("parameterized types are not runtime validators")
Expected output
12
parameterized types are not runtime validators
Example checked with CPython 3.14.8, CPython 3.15.0, Pyodide Python 3.13.2.
Common mistake
A list annotation does not make the list homogeneous. Validate untrusted elements separately and let static analysis check ordinary code.
Try it yourself
Annotate a mapping from student names to lists of scores. Describe which checks are needed when that mapping comes from JSON.
Read more: Python 3.9 release notes · PEP 585
Introduced in Python 3.9 · Standard library
Remove a prefix or suffix exactly
removeprefix() and removesuffix() remove one whole matching affix. If it is absent, the string's contents stay unchanged. They are useful for filenames, identifiers, and labels with a known literal wrapper.
The older strip, lstrip, and rstrip methods take sets of characters rather than a whole substring. For example, removing the character set .txt from an end is different from removing exactly the suffix .txt.
Removal is case-sensitive and applies once. These operations return strings and do not modify the original. An empty affix leaves the contents unchanged.
Worked example
Minimum Python 3.9
name = "draft_report.txt" print(name.removeprefix("draft_")) print(name.removesuffix(".txt")) print("draft_draft_report".removeprefix("draft_")) print("Report.TXT".removesuffix(".txt"))
Expected output
report.txt
draft_report
draft_report
Report.TXT
Example checked with CPython 3.14.8, CPython 3.15.0, Pyodide Python 3.13.2.
Common mistake
Do not replace exact-suffix removal with rstrip(".txt"); that can remove unrelated trailing characters.
Try it yourself
Apply both methods to draft_report.txt to produce report. What should happen when the prefix is absent?
Read more: Python 3.9 release notes · PEP 616
Recap
Merge dictionaries with explicit precedence, annotate built-in collections, and remove a whole prefix or suffix without strip confusion. Prefer the clearest form that works on your project's supported Python versions.
Read the full Python 3.9 release notes →