Python 3.14 Preview: Better Syntax Error Messages

Python 3.14 Preview: Better Syntax Error Messages

by Philipp Acsany Publication date Oct 01, 2025 Reading time estimate 26m intermediate python

Python 3.14 brings a fresh batch of improvements to error messages that’ll make debugging feel less like detective work and more like having a helpful colleague point out exactly what went wrong. These refinements build on the clearer tracebacks introduced in recent releases and focus on the mistakes Python programmers make most often.

By the end of this tutorial, you’ll understand that:

  • Python 3.14’s improved error messages help you debug code more efficiently.
  • There are ten error message enhancements in 3.14 that cover common mistakes, from keyword typos to misusing async with.
  • These improvements can help you catch common coding mistakes faster.
  • Python’s error messages have evolved from version 3.10 through 3.14.
  • Better error messages accelerate your learning and development process.

There are many other improvements and new features coming in Python 3.14. The highlights include the following:

To try any of the examples in this tutorial, you need to use Python 3.14. The tutorials How to Install Python on Your System: A Guide and Managing Multiple Python Versions With pyenv walk you through several options for adding a new version of Python to your system.

Take the Quiz: Test your knowledge with our interactive “Python 3.14 Preview: Better Syntax Error Messages” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python 3.14 Preview: Better Syntax Error Messages

Explore how Python 3.14 improves error messages with clearer explanations, actionable hints, and better debugging support for developers.

Better Error Messages in Python 3.14

When Python 3.9 introduced a new parsing expression grammar (PEG) parser for the language, it opened the door to better error messages in Python 3.10. Python 3.11 followed with even better error messages, and that same effort continued in Python 3.12.

Python 3.13 refined these messages further with improved formatting and clearer explanations, making multiline errors more readable and adding context to complex error situations. These improvements build upon PEP 657, which introduced fine-grained error locations in tracebacks in Python 3.11.

Now, Python 3.14 takes another step forward, alongside other significant changes like PEP 779, which makes the free-threaded build officially supported, and PEP 765, which disallows using return, break, or continue to exit a finally block. What makes the error message enhancements in Python 3.14 special is their focus on common mistakes.

Each improved error message follows a consistent pattern:

  1. It identifies the mistake.
  2. It explains what’s wrong in plain English.
  3. It suggests a likely fix when possible.

The error message improvements in Python 3.14 cover SyntaxError, ValueError, and TypeError messages. For an overview of the ten improvements you’ll explore in this tutorial, expand the collapsible section below:

  • Keyword TyposSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: invalid syntax. Did you mean 'for'?

  • elif After elseSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: 'elif' block follows an 'else' block

  • Conditional ExpressionsSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: expected expression after 'else', but statement is given

  • String ClosureSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: invalid syntax. Is this intended to be part of the string?

  • String PrefixesSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: 'b' and 'f' prefixes are incompatible

  • Unpacking ErrorsValueError
    ⭕️ Previous: too many values to unpack (expected 2)
    Improved: too many values to unpack (expected 2, got 3)

  • as TargetsSyntaxError
    ⭕️ Previous: invalid syntax
    Improved: cannot use list as import target

  • Unhashable TypesTypeError
    ⭕️ Previous: unhashable type: 'list'
    Improved: cannot use 'list' as a dict key (unhashable type: 'list')

  • math Domain ErrorsValueError
    ⭕️ Previous: math domain error
    Improved: expected a nonnegative input, got -1.0

  • async with ErrorsTypeError
    ⭕️ Previous: 'TaskGroup' object does not support the context manager protocol
    Improved: object does not support the context manager protocol...Did you mean to use 'async with'?

The examples in this tutorial show both the error messages from Python 3.13 and the improved messages in Python 3.14, so you can see the differences even if you haven’t installed 3.14 yet.

For a general overview of Python’s exception system, see Python’s Built-in Exceptions: A Walkthrough With Examples, or to learn about raising exceptions, check out Python’s raise: Effectively Raising Exceptions in Your Code.

Clearer Keyword Typo Suggestions

A typo is usually a tiny mistake, sometimes just one extra letter, but it’s enough to break your code completely. Typos that involve Python keywords are among the most common syntax errors in Python code.

In Python 3.13 and earlier, a typo in a keyword produces a generic syntax error that offers no guidance about what might be wrong:

Python Python 3.13
>>> forr i in range(5):
  File "<python-input-0>", line 1
    forr i in range(5):
         ^
SyntaxError: invalid syntax

The error points to the problem area with a helpful caret symbol (^), which at least tells you where Python found the error. However, it doesn’t suggest what you might have meant. The message “invalid syntax” is technically correct but not particularly helpful in practice.

You have to figure out on your own that forr should actually be for. It might be obvious once you spot it, but finding that single wrong letter can take a surprisingly long time when you’re focused on logic rather than spelling.

Python 3.14 recognizes when you type something close to a Python keyword and offers a helpful suggestion that immediately points you to the fix:

Python Python 3.14
>>> forr i in range(5):
  File "<python-input-0>", line 1
    forr i in range(5):
    ^^^^
SyntaxError: invalid syntax. Did you mean 'for'?

The improved error messages in Python 3.14 use edit-distance metrics to detect when an unknown word closely matches a Python keyword. But you should still be careful and double-check Python’s suggestion:

Python Python 3.14
>>> why True:
  File "<python-input-0>", line 1
    why True:
    ^^^
SyntaxError: invalid syntax. Did you mean 'with'?

Sometimes Python doesn’t suggest the correct keyword if another Python keyword more closely matches your typo. Also, a suggestion only appears when the typo is within a reasonable edit distance of a valid keyword—otherwise, you’ll still get a plain old SyntaxError that just says “invalid syntax” without any suggestions.

Python 3.14 doesn’t stop at simple typos. It also helps when you misplace keywords in control structures.

Stricter elif-After-else Block Errors

The if, elif, and else keywords are part of Python’s conditional statements. When writing this type of statement in Python, you must follow a specific structure: the if condition comes first, then any number of elif blocks for additional conditions, and finally an optional else to catch everything that doesn’t match. But it’s surprisingly easy to accidentally place an elif after the else block.

If you don’t follow the correct order, then you’ll get a SyntaxError. In Python 3.13, you get a generic “invalid syntax” error that points to the elif keyword:

Python Python 3.13
>>> if x > 0:
...     print("positive")
... else:
...     print("not positive")
... elif x == 0:  # This is invalid
...     print("zero")
...
  File "<python-input-0>", line 5
    elif x == 0:  # This is invalid
    ^^^^
SyntaxError: invalid syntax

While the caret symbols show you where Python found the error, there’s no explanation about why this particular placement is wrong. You may wonder if elif is valid at all and could even be tempted to try writing else if or if else.

In this situation, Python 3.14 provides a specific explanation that immediately identifies the structural problem:

Python Python 3.14
>>> if x > 0:
...    print("positive")
... else:
...    print("not positive")
... elif x == 0:
...    print("zero")
...
  File "<python-input-0>", line 5
    elif x == 0:
    ^^^^
SyntaxError: 'elif' block follows an 'else' block

The new message immediately tells you the problem: elif can’t come after else. This helps you understand that else must be the final block in a conditional chain—a catch-all for any conditions not handled by if or elif.

Python 3.14 takes it a step further. In addition to conditional statements, it also clarifies mistakes in conditional expressions—the single-line cousin of if, elif, and else.

More Explicit Conditional Expression Errors

In addition to conditional statements, Python supports another decision-making entity called conditional expressions, also called ternary operators:

Python Syntax
variable = expression_1 if condition else expression_2

Conditional expressions provide a compact way to choose between two values based on a condition. As the name suggests, conditional expressions must contain expressions, not statements. Here’s a summary of the difference between expressions and statements:

The distinction between expressions and statements is crucial in Python but not always intuitive. Expressions evaluate to values:

Python
>>> 2 + 2
4

>>> len("Python")
6

>>> "hello".upper()
'HELLO'

In Python, a statement is a complete instruction that tells the interpreter to perform an action:

Python
>>> # Assignment statement
>>> x = 10

>>> # Expression statement
>>> x + 5
15

>>> # Conditional statement
>>> if x > 5:
...     print("x is greater than 5")
...
x is greater than 5

>>> # Loop statement
>>> for i in range(3):
...     print(i)
...
0
1
2

This code snippet includes various statements, including an assignment (x = 10), an expression (x + 5), a conditional (if), and a for loop statement.

Unlike expressions, which produce values, statements execute operations or control program flow. Every line of executable code in Python is a statement, although some statements can span multiple lines.

In Python, the pass keyword is a placeholder statement that allows you to write syntactically correct code without executing any operations.

Here’s what happens in Python 3.13 when you accidentally use pass in a conditional expression:

Python Python 3.13
>>> 1 if True else pass
  File "<python-input-0>", line 1
    1 if True else pass
                   ^^^^
SyntaxError: invalid syntax

Python 3.13’s generic “invalid syntax” error doesn’t explain why pass isn’t allowed here. The error message gives you no guidance about the difference between an expression vs a statement.

Python 3.14 clarifies the issue with a message that teaches you about this fundamental distinction:

Python Python 3.14
>>> 1 if True else pass
  File "<python-input-0>", line 1
    1 if True else pass
                   ^^^^
SyntaxError: expected expression after 'else', but statement is given

The message now explains that after else in a conditional expression, Python expects an expression rather than a statement like pass.

If you want to get “nothing” as a value in a conditional expression, you’d use None instead of pass. Who knows? Maybe Python 3.15 will add this as an improved error message suggestion.

While conditional expressions deal with values, strings present a different set of challenges, especially when it comes to matching quotation marks.

Helpful String Closure Errors

Working with strings is one of the most fundamental tasks in programming, yet it’s also a consistent source of syntax errors. For example, you write what seems natural, putting quotes around the spoken words:

Python Python 3.13
>>> message = "She said "Hello" to everyone"
  File "<python-input-0>", line 1
    message = "She said "Hello" to everyone"
                         ^^^^^
SyntaxError: invalid syntax

Looking at this error in Python 3.13, you can see that Python marks Hello as the problem with those caret symbols. However, the generic “invalid syntax” message doesn’t help you understand what’s actually happening.

Python interprets the second quotation mark before Hello as closing the string that started with the first quotation mark. Python 3.14 recognizes this common pattern and offers targeted guidance:

Python Python 3.14
>>> message = "She said "Hello" to everyone"
  File "<python-input-0>", line 1
    message = "She said "Hello" to everyone"
                         ^^^^^
SyntaxError: invalid syntax. Is this intended to be part of the string?

In Python 3.14, incorrectly closed strings raise a SyntaxError with the message, “Is this intended to be part of the string?” This question reframes the problem from a syntax error to a string-formatting issue. Instead of wondering what’s syntactically wrong, you now understand that you need to handle quotes within quotes. To learn more about how to fix this kind of syntax error, expand the collapsible section below:

To fix this syntax error, you can use different quote types inside the string:

Python
>>> message = "She said 'Hello' to everyone"
>>> message = 'She said "Hello" to everyone'

Alternatively, you can use the same quote types and escape the quotes inside the string with backslashes:

Python
>>> message = "She said \"Hello\" to everyone"
>>> message = 'She said \'Hello\' to everyone'

Each solution has its place. Using different quotes is often the cleanest approach for basic cases. Escaping with backslashes works when you need to use the same quote type throughout.

The improved suggestions in Python 3.14 for incorrectly closed strings catch various quote-related issues beyond simple dialog. They help with JSON data that need embedded quotes, SQL queries with string literals, regular expressions that require quote matching, and HTML snippets with quoted attributes.

Clearer String Prefix Combination Errors

Python’s string prefix system is powerful but can be confusing when you’re learning which combinations can be used together. Each case-sensitive prefix serves a specific purpose:

Prefix Purpose
r Creates raw strings that treat backslashes literally
b Creates a bytes object for binary data
f Enables f-strings with embedded expressions
u Explicitly marks Unicode strings

Python 3.14 also introduces template strings (t-strings), which add another t prefix to the mix.

The confusion arises when developers try to combine features that seem like they should work together, but a value can’t be both text and binary data at the same time. They’re different types with distinct internal representations.

Here’s what happens when you try to combine incompatible string prefixes in Python 3.13:

Python Python 3.13
>>> text = fb"Binary {text}"
  File "<python-input-0>", line 1
    text = fb"Binary {text}"
             ^^^^^^^^^^^^^^^
SyntaxError: invalid syntax

The error in Python 3.13 points to the string with a generic “invalid syntax” message that doesn’t explain what’s wrong with the fb prefix combination.

Python 3.14 explicitly states the incompatibility, making the issue clear:

Python Python 3.14
>>> text = fb"Binary {text}"
  File "<python-input-0>", line 1
    text = fb"Binary {text}"
           ^^
SyntaxError: 'b' and 'f' prefixes are incompatible

The message “‘b’ and ‘f’ prefixes are incompatible” immediately explains the problem. Python’s f-strings need to evaluate Python expressions and convert them to string representations, which requires working with text. Bytes objects aren’t text. They’re sequences of raw bytes, so they can’t participate in the string formatting system.

Consistent Unpacking Assignment Errors

Python’s iterable unpacking lets you assign multiple values to multiple variables in one clean statement. But there’s a catch: the number of variables on the left must match the number of values on the right. When they don’t match, you get a ValueError—one that, in earlier versions of Python, only told you half the story.

Here’s what happens in Python 3.13 when you try to unpack three values into four variables:

Python Python 3.13
>>> dog, age, city, hobbies = ["Frieda", 8, "Berlin"]
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    dog, age, city, hobbies = ["Frieda", 8, "Berlin"]
    ^^^^^^^^^^^^^^^^^^^^^^^
ValueError: not enough values to unpack (expected 4, got 3)

If you don’t provide enough values to unpack, then Python 3.13 makes it clear what went wrong. In the example above, Python expected four values but only got three.

Interestingly, when you provide too many values to unpack, Python 3.13 doesn’t tell you how many values it got:

Python Python 3.13
>>> dog, age = ["Frieda", 8, "Berlin"]
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    dog, age = ["Frieda", 8, "Berlin"]
    ^^^^^^^^
ValueError: too many values to unpack (expected 2)

Python 3.13 tells you that there are too many values and that it expected two, which is helpful to a point. But it doesn’t tell you how many values you actually provided.

Python 3.14 adds this missing piece of information, completing the picture:

Python Python 3.14
>>> dog, age = ["Frieda", 8, "Berlin"]
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    dog, age = ["Frieda", 8, "Berlin"]
    ^^^^^^^^
ValueError: too many values to unpack (expected 2, got 3)

The consistency in Python 3.14 now means all unpacking errors show both expected and actual counts. With the complete “expected X, got Y” information, you can immediately see which side needs fixing.

While unpacking deals with matching values to variables, Python also has constraints on what can be used as a target for assignment-like operations.

Improved as Target Errors

The as keyword creates an alias or alternative name for a module, exception, or context manager. You can also use as to intercept a subpattern in structural pattern matching. Using as is especially common in import statements.

Under the hood, as creates a binding in the local namespace, essentially doing an assignment. But unlike regular assignment with the equal sign (=), the as keyword only accepts plain identifiers.

Here’s a scenario in Python 3.13 where you might try to import a module with an alias that uses list notation, perhaps to organize imports dynamically:

Python Python 3.13
>>> import sys as [alias]
  File "<python-input-0>", line 1
    import sys as [alias
                  ^
SyntaxError: invalid syntax

In Python 3.13, the caret (^) points to the problem, but the generic “invalid syntax” message doesn’t explain why a list isn’t a valid target for as in an import.

Python 3.14 provides a specific explanation that clarifies the restriction:

Python Python 3.14
>>> import sys as [alias]
  File "<python-input-0>", line 1
    import sys as [alias]
                  ^^^^^^^
SyntaxError: cannot use list as import target

The message “cannot use list as import target” immediately tells you that lists aren’t allowed after as in import statements. In other words, aliases must be names that can become variables in your namespace.

Besides import statements, you’ll find the improved error messages helpful in most situations where you can use as. For example, in try ... except blocks or when using structural pattern matching.

Contextual Unhashable Type Errors

In Python, an object is considered hashable if it has a hash value that remains constant during the object’s lifetime.

Hashable objects can be used as a key in a dictionary or as an element in a set, since both data structures rely on hashing to efficiently look up and store elements.

The confusion typically starts when you try to use familiar data structures in ways that seem logical but violate hashability rules. You might want to use a list as a dictionary key to map sequences to values:

Python Python 3.13
>>> grid = {[0, 0]: "Label", [0, 1]: "Input"}
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    grid = {[0, 0]: "Label", [0, 1]: "Input"}
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: unhashable type: 'list'

Python 3.13’s error message tells you that lists are unhashable, which is technically correct but not particularly helpful if you don’t understand what hashability means or why it matters.

Python 3.14 adds crucial context that connects the error to your specific action:

Python Python 3.14
>>> grid = {[0, 0]: "Label", [0, 1]: "Input"}
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    grid = {[0, 0]: "Label", [0, 1]: "Input"}
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: cannot use 'list' as a dict key (unhashable type: 'list')

The improved TypeError message—“cannot use ‘list’ as a dict key (unhashable type: ‘list’)”—explains both what you’re trying to do and why it fails:

  • Problem: You’re trying to use a list as a dictionary key.
  • Why it fails: Lists are unhashable in Python.

In Python 3.14, this improved error message immediately suggests the solution. If lists can’t be dict keys because they’re unhashable, then you need a hashable data type like a tuple as a key:

Python
>>> grid = {(0, 0): "Label", (0, 1): "Input"}

Since tuples are immutable in Python, they’re hashable and you can use them as dictionary keys.

The pattern of improved, context-specific error messages extends beyond type errors to include arithmetic operations as well.

Descriptive Math Domain Errors

Mathematical functions have specific domains where they’re mathematically defined. When you pass values outside these domains to functions in Python’s math module, you get a ValueError. However, historically, the error messages haven’t been particularly informative.

In Python 3.13, when you try to calculate the square root of a negative number, you get a generic error message:

Python Python 3.13
>>> import math
>>> math.sqrt(-1)
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    math.sqrt(-1)
    ~~~~~~~~~^^^^
ValueError: math domain error

While the message “math domain error” is technically correct, it doesn’t help you understand what went wrong. You know there’s a domain issue, but not what the valid domain is or which value you provided that violated it.

Python 3.14 replaces this generic message with specific information about what the function expects:

Python Python 3.14
>>> import math
>>> math.sqrt(-1)
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    math.sqrt(-1)
    ~~~~~~~~~^^^^
ValueError: expected a nonnegative input, got -1.0

The improved message, “expected a nonnegative input, got -1.0”, tells you that the function needs a nonnegative number and shows what you provided instead. To fix your input data, use absolute values or switch to the cmath module for complex-number support.

For developers working with asynchronous code, Python 3.14 addresses a particularly confusing error that occurs when mixing synchronous and asynchronous context managers.

Corrective async with Usage Errors

The with statement also has an asynchronous version, async with. This construct is quite common in async code, as many I/O-bound tasks involve setup and teardown phases.

Say you’re building an async web scraper and you need to manage multiple concurrent tasks. The asyncio.TaskGroup is perfect for this, but in your haste, you use the familiar with statement:

Python Python 3.13
>>> import asyncio
>>> async def process_data():
...     with asyncio.TaskGroup() as tg:
...         pass
...
>>> asyncio.run(process_data())
Traceback (most recent call last):
  ...
  File "<python-input-0>", line 3, in process_data
    with asyncio.TaskGroup() as tg:
         ~~~~~~~~~~~~~~~~~^^
TypeError: 'TaskGroup' object does not support the context manager protocol

The error message in Python 3.13 says that TaskGroup doesn’t support the context manager protocol, which is confusing and technically incorrect.

TaskGroup does support a context manager protocol—just not the synchronous one. It implements .__aenter__() and .__aexit__() for asynchronous context management, not .__enter__() and .__exit__() for synchronous context management.

Python 3.14 recognizes this common mistake—using with instead of async with—and provides a more detailed explanation:

Python Python 3.14
>>> import asyncio
>>> async def process_data():
...      with asyncio.TaskGroup() as tg:
...           pass
...
>>> asyncio.run(process_data())
Traceback (most recent call last):
  ...
  File "<python-input-0>", line 3, in process_data
    with asyncio.TaskGroup() as tg:
         ~~~~~~~~~~~~~~~~~^^
TypeError: 'asyncio.taskgroups.TaskGroup' object does not support
⮑ the context manager protocol (missed __exit__ method)
⮑ but it supports the asynchronous context manager protocol.
⮑ Did you mean to use 'async with'?

The suggestion “Did you mean to use ‘async with’?” immediately points you to the solution. The message acknowledges that TaskGroup is indeed a context manager, just not the type you’re trying to use.

The improved error message also works in reverse, catching the opposite mistake when you use async with on a synchronous context manager:

Python Python 3.14
>>> import asyncio
>>> async def read_file():
...     async with open("data.txt") as f:
...         return f.read()
...
>>> asyncio.run(read_file())
Traceback (most recent call last):
  ...
  File "<python-input-0>", line 3, in read_file
    async with open("data.txt") as f:
               ~~~~^^^^^^^^^^^^
TypeError: '_io.TextIOWrapper' object does not support
⮑ the asynchronous context manager protocol (missed __aexit__ method)
⮑ but it supports the context manager protocol.
⮑ Did you mean to use 'with'?

Here, you’re trying to use async with on a regular file object that only supports synchronous context management. The error message correctly suggests using with instead.

Conclusion

Python 3.14’s improved error messages represent more than just better debugging—they reflect Python’s ongoing commitment to being a language that teaches as it runs. These ten error message enhancements transform cryptic error messages into helpful guidance that both points you to solutions and deepens your understanding of Python’s design principles.

In the tutorial, you’ve learned how Python 3.14 improves error messages for:

  • Common syntax errors by suggesting correct keywords for typos and explaining proper block order in conditional chains
  • String and bytes literals by identifying invalid prefix combinations and clarifying when quotes might be part of the content
  • Unpacking and assignment operations by showing expected vs actual value counts and explaining valid assignment targets
  • Type-related operations by providing context about hashability requirements for sets and dictionaries, and mathematical domain restrictions
  • Context manager usage by distinguishing between synchronous and asynchronous protocols and suggesting the appropriate syntax

As you encounter these new error messages in your own code, you’ll appreciate how they guide you toward quick fixes rather than leaving you to decipher vague clues. For the complete list of changes in Python 3.14, consult the official What’s New in Python 3.14 documentation.

Frequently Asked Questions

Now that you have some experience with the improved error messages in Python 3.14, you can use the questions and answers below to check your understanding and recap what you’ve learned.

These FAQs are related to the most important concepts you’ve covered in this tutorial. Click the Show/Hide toggle beside each question to reveal the answer.

When you place elif after else, you break the required order of if, then optional elif blocks, and finally an optional else. You can fix this by moving the elif before the else or by nesting a new if inside the else block.

This message means you wrote a statement like pass where Python expects a value. To fix it, provide an expression such as None or a valid value-producing expression.

This error occurs when you close a string too early with mismatched quotes. You can fix it by switching the outer or inner quote type or by escaping the inner quotes.

The b and f string prefixes are incompatible because you can’t combine text formatting with a binary bytes literal. You can address this by using an f-string for text or by first building the text, then encoding it with str.encode() or bytes().

You can’t use a mutable and unhashable type as a key because Python can’t compute a stable hash() for it. You can fix this by using an immutable tuple instead or by converting the list with tuple().

Take the Quiz: Test your knowledge with our interactive “Python 3.14 Preview: Better Syntax Error Messages” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python 3.14 Preview: Better Syntax Error Messages

Explore how Python 3.14 improves error messages with clearer explanations, actionable hints, and better debugging support for developers.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Philipp Acsany

Philipp is a core member of the Real Python team. He creates tutorials, records video courses, and hosts Office Hours sessions to support your journey to becoming a skilled and fulfilled Python developer.

» More about Philipp

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics: intermediate python