Python is recursively checking each element of the dictionaries to ensure equality. See the C dict_equal() implementation, which checks each and every key and value (provided the dictionaries are the same length); if dictionary b has the same key, then a PyObject_RichCompareBool tests if the values match too; this is essentially a recursive call.

Dictionaries are not hashable because their __hash__ attribute is set to None, and most of all they are mutable, which is disallowed when used as a dictionary key.

If you were to use a dictionary as a key, and through an existing reference then change the key, then that key would no longer slot to the same position in the hash table. Using another, equal dictionary (be it equal to the unchanged dictionary or the changed dictionary) to try and retrieve the value would now no longer work because the wrong slot would be picked, or the key would no longer be equal.

Answer from Martijn Pieters on Stack Overflow
🌐
W3Schools
w3schools.com › python › python_ref_dictionary.asp
Python Dictionary Methods
Python Dictionaries Access Items Change Items Add Items Remove Items Loop Dictionaries Copy Dictionaries Nested Dictionaries Dictionary Methods Dictionary Exercises Code Challenge Python If...Else · Python If Python Elif Python Else Shorthand If Logical Operators Nested If Pass Statement Code ...
🌐
Real Python
realpython.com › python-dicts
Dictionaries in Python – Real Python
April 8, 2026 - Keep in mind that .copy() only ... operators you can use with dictionaries. The most notable ones are the membership, equality, and union operators....
Discussions

What does the == operator actually do on a Python dictionary? - Stack Overflow
Is Python recursively checking each element of the dictionaries to ensure equality? Is it making sure the keys are identically matched, and the values are also identically matched? Is there documentation that specifies exactly what == on a dictionary means? Or whether I have to implement my own version of checking for equality? (If the == operator ... More on stackoverflow.com
🌐 stackoverflow.com
python - When to use dictionary | (merge) vs |= (update) operator - Stack Overflow
When to use the merge vs update operators on dictionaries. The following examples, while there are differences in how to call them, their output is the same. a = {1: 'a', 2: 'b', 3: 'c', 6: 'in bot... More on stackoverflow.com
🌐 stackoverflow.com
in operator for dictionary VS. in operator for dict.keys()
n in d and n in d.keys() do essentially the exact same thing. .keys() returns a dict_keys object, which behaves mostly set-like and is really just a view on its parent dictionary's state. Any difference in execution time is probably down to the overhead of the additional function call. Dictionaries in Python are implemented as hash maps. The key is converted to a number via a hashing function, and that number determines which of several buckets the key falls into. Computing the hashing function and determining the bucket that corresponds to the result can be done in constant time. If more than one key resides within the bucket, the correct one is determined via a linear search. However, with a sufficient number of buckets and a well chosen hashing function, the number of keys per bucket should be small enough that a dictionary lookup is still essentially constant time. More on reddit.com
🌐 r/learnpython
26
9
January 1, 2022
python - What does `**` mean in the expression `dict(d1, **d2)`? - Stack Overflow
I am intrigued by the following python expression: ... The task is to merge 2 dictionaries into a third one, and the above expression accomplishes the task just fine. I am interested in the ** operator and what exactly is it doing to the expression. More on stackoverflow.com
🌐 stackoverflow.com
🌐
Python
peps.python.org › pep-0584
PEP 584 – Add Union Operators To dict | peps.python.org
PEP 584: Add + and += operators to the built-in dict class. ... Merging two dictionaries in an expression is a frequently requested feature.
🌐
GeeksforGeeks
geeksforgeeks.org › python-operators-for-sets-and-dictionaries
Python Operators for Sets and Dictionaries - GeeksforGeeks
May 1, 2025 - These operators help with retrieving, updating, comparing and checking the existence of keys. Let’s explore them. These are used to get, set, or delete values in a dictionary.
🌐
Real Python
realpython.com › lessons › operators-and-methods-dictionaries-python
Operators and Methods for Dictionaries in Python (Video) – Real Python
You can use the in operator together with short-circuit evaluation to avoid raising an error when trying to access a key that is not in the dictionary. The len() function returns the number of key-value pairs in a dictionary. To learn more about dictionaries, you might want to check out Python Basics: Dictionaries.
Published   July 30, 2019
Top answer
1 of 3
35

Python is recursively checking each element of the dictionaries to ensure equality. See the C dict_equal() implementation, which checks each and every key and value (provided the dictionaries are the same length); if dictionary b has the same key, then a PyObject_RichCompareBool tests if the values match too; this is essentially a recursive call.

Dictionaries are not hashable because their __hash__ attribute is set to None, and most of all they are mutable, which is disallowed when used as a dictionary key.

If you were to use a dictionary as a key, and through an existing reference then change the key, then that key would no longer slot to the same position in the hash table. Using another, equal dictionary (be it equal to the unchanged dictionary or the changed dictionary) to try and retrieve the value would now no longer work because the wrong slot would be picked, or the key would no longer be equal.

2 of 3
20

From docs:

Mappings (dictionaries) compare equal if and only if their sorted (key, value) lists compare equal .[5] Outcomes other than equality are resolved consistently, but are not otherwise defined. [6]

Footnote [5]:

The implementation computes this efficiently, without constructing lists or sorting.

Footnote [6]:

Earlier versions of Python used lexicographic comparison of the sorted (key, value) lists, but this was very expensive for the common case of comparing for equality. An even earlier version of Python compared dictionaries by identity only, but this caused surprises because people expected to be able to test a dictionary for emptiness by comparing it to {}.

🌐
W3Schools
w3schools.com › python › python_dictionaries.asp
Python Dictionaries
Python Dictionaries Access Items Change Items Add Items Remove Items Loop Dictionaries Copy Dictionaries Nested Dictionaries Dictionary Methods Dictionary Exercises Code Challenge Python If...Else · Python If Python Elif Python Else Shorthand If Logical Operators Nested If Pass Statement Code ...
Find elsewhere
🌐
The Teclado Blog
blog.teclado.com › python-dictionary-merge-update-operators
Dictionary Merge and Update Operators in Python 3.9
May 4, 2021 - Python 3.9 was released on Oct. 5, 2020 and it introduces some neat features and optimizations including PEP 584, Union Operators in the built-in class dict; the so-called Dictionary Merge and Update Operators.
Top answer
1 of 1
5

The |= operator just updates your original dictionary with the result of the union operation. The | operator returns a new dictionary that is the union of the two dicts. Let's say we have two sets

Copya = {'hello', 'world', 'abc', 'def'}
b = {'abc', 'ghi', 'jkl'}

The operation a |= b is similar to a = a | b in much the same way as a += b is similar to a = a + b for lists.

Copya = {'hello', 'world', 'abc', 'def'}
al = list(a)
b = {'abc', 'ghi', 'jkl'}
bl = list(b)

print("Before: ", hex(id(a)), a)
a = a | b
print("After: ", hex(id(a)), a)
# Output: 
# Before:  0x1aa0186f128 {'world', 'def', 'abc', 'hello'}
# After:  0x1aa0186f828 {'world', 'ghi', 'hello', 'jkl', 'def', 'abc'}

print("Before: ", hex(id(al)), al)
al = al + bl
print("After: ", hex(id(al)), al)
# Output: 
# Before:  0x1aa0187a248 ['world', 'def', 'abc', 'hello']
# After:  0x1aa0366bdc8 ['world', 'def', 'abc', 'hello', 'jkl', 'abc', 'ghi']

Evidently, a is now a new set at a different location in memory.

Copya = {'hello', 'world', 'abc', 'def'}
al = list(a)
b = {'abc', 'ghi', 'jkl'}
bl = list(b)

print("Before", hex(id(a)), a)
a |= b
print("After", hex(id(a)), a)
# Output: 
# Before 0x1aa0186f128 {'world', 'def', 'abc', 'hello'}
# After 0x1aa0186f128 {'world', 'ghi', 'hello', 'jkl', 'def', 'abc'}

print("Before", hex(id(al)), al)
al += bl
print("After", hex(id(al)), al)
# Output:
# Before 0x1aa03646888 ['world', 'def', 'abc', 'hello']
# After 0x1aa03646888 ['world', 'def', 'abc', 'hello', 'jkl', 'abc', 'ghi']

In this case, a is still the old set at a same location in memory, but its contents have been updated.

🌐
Afternerd
afternerd.com › blog › dict-union-operators
Python: Dictionary Union Operators Explained - Afternerd
February 14, 2021 - If you want to modify the dictionary d1 in place, here is how to do it using the union operator. >>> d1 {'name': 'Alice', 'age': 25, 'job': 'SWE'} >>> d2 {'job': 'Senior SWE', 'location': 'US'} >>> d1 |= d2 >>> d1 {'name': 'Alice', 'age': 25, 'job': 'Senior SWE', 'location': 'US'} Starting Python 3.9+, you can now use the Union operator to merge two dictionaries together.
🌐
Reddit
reddit.com › r/learnpython › in operator for dictionary vs. in operator for dict.keys()
r/learnpython on Reddit: in operator for dictionary VS. in operator for dict.keys()
January 1, 2022 -

Main Questions are at end of post...

I'm going over the Two Sum problem on LeetCode, and the optimal solution was to use a dictionary. This involved a "look up" to see if a dictionary key existed. Can someone explain to me how exactly python "looks up" a dictionary key to see if it exists. Particularly in comparing these two lines of code:

# where n is a key, and d is a dictionary
if n in d:

# where n is a key, and d.keys() is a viewing object (a list??)
if n in d.keys():

I was confused because these two methods took around the same time on leetcode, and I thought the second method would have a time complexity of O(n) because (I thought) it was just a list.

I did further testing with the timeit module... my code and its results are below:

# checking time complexity of dict key look up methods
# basically I'm running both methods and checking how much time each takes as the dictionary grows
# I thought that the second method would take longer and longer as the dictionary grew, but that doesn't seem to be the case

Code:

from timeit import Timer

in_op = Timer("x in d", "from __main__ import x, d")
key_method = Timer("x in d.keys()", "from __main__ import x, d")

for i in range(1_000_000, 10_000_001, 1_000_000):
	x = i
	d = {i:0 for i in range(i)}
	d[i] = 'yes'
	in_op_time = in_op.timeit(1000)
	d = {i:0 for i in range(i)}
	d[i] = 'yes'
	key_method_time = key_method.timeit(1000)
	print(f"{in_op_time=} and {key_method_time=}")

Results:

in_op_time=3.087499999999965e-05 and key_method_time=7.250000000000312e-05
in_op_time=3.008300000001407e-05 and key_method_time=6.941599999998882e-05
in_op_time=2.9749999999939547e-05 and key_method_time=6.862500000004434e-05
in_op_time=3.0790999999918967e-05 and key_method_time=6.945800000002222e-05
in_op_time=3.0165999999942628e-05 and key_method_time=7.025000000027148e-05
in_op_time=3.0250000000009436e-05 and key_method_time=6.829099999983157e-05
in_op_time=3.00840000000413e-05 and key_method_time=6.845799999988245e-05
in_op_time=2.958299999988867e-05 and key_method_time=6.824999999999193e-05
in_op_time=2.954200000004903e-05 and key_method_time=6.891600000002995e-05
in_op_time=2.9916999999990423e-05 and key_method_time=6.833300000064213e-05

My questions are:

  1. How does the first case "know" that the key doesn't exist? I understand when you try to access a key that doesn't exist, python gives an error, so I'm assuming that's the same mechanism?

  2. If the dict.keys() doesn't return a list, then what does it return?

  3. How does the in operator work with dict.keys()?... Like how does it bypass the returned object and go straight to looking up the key with normal dictionary methods?

🌐
W3Schools
w3schools.com › python › python_operators.asp
Python Operators
Python Examples Python Compiler Python Exercises Python Quiz Python Challenges Python Practice Problems Python Server Python Syllabus Python Study Plan Python Interview Q&A Python Bootcamp Python Training ... Operators are used to perform operations on variables and values.
🌐
DevGenius
blog.devgenius.io › python-dictionary-operations-68e19b08ea30
Python Dictionary Operations. Most common operations on dictionaries… | by Hanzel Godinez H. | Dev Genius
July 26, 2020 - These operations allow us to define or create a dictionary. ... Creates an empty dictionary or a dictionary with some initial values.
🌐
O'Reilly
oreilly.com › library › view › python-in-a › 0596100469 › ch04s08.html
Dictionary Operations - Python in a Nutshell, 2nd Edition [Book]
July 14, 2006 - Since dictionaries are containers, the built-in len function can take a dictionary as its single argument and return the number of items (key/value pairs) in the dictionary object.
Author   Alex Martelli
Published   2006
Pages   734
🌐
LWN.net
lwn.net › Articles › 635397
New operators for Python dicts? [LWN.net]
March 4, 2015 - In applications, you normally just need the update functionality for dictionaries. If you do need a copy, you can create a copy explicitly - but those cases are usually rare. Having one of those operators without the other seems a bit strange to some, though. Operators in Python are implemented as special methods on objects, so a + b becomes a.__add__(b) (similarly, += uses the __iadd__() special method).
🌐
GeeksforGeeks
geeksforgeeks.org › python › merging-and-updating-dictionary-operators-in-python-3-9
Merging and Updating Dictionary Operators in Python 3.9 - GeeksforGeeks
July 12, 2025 - Using ** in Python: There is a trick in Python where we can merge two dictionaries using single expression and store it in a third dictionary. The expression is **. This does not affect the other two dictionaries. ** allows us to pass multiple arguments to a function directly using a dictionary by expanding the contents of the dictionary in the form of collection of key value pairs.
🌐
Towards Data Science
towardsdatascience.com › home › latest › unpacking operators in python
Unpacking Operators in Python | Towards Data Science
January 21, 2025 - In this tutorial, we learned how to use the * operator to unpack iterable objects and the operator to unpack dictionaries. We also learned many ways to utilize these operators to accomplish many different tasks.
🌐
Python documentation
docs.python.org › 3 › tutorial › datastructures.html
5. Data Structures — Python 3.14.6 documentation
A pair of braces creates an empty ... dictionaries are written on output. The main operations on a dictionary are storing a value with some key ......
🌐
Python.org
discuss.python.org › ideas
Add Difference Operators To Dict - Page 2 - Ideas - Discussions on Python.org
April 21, 2024 - Why is it a problem that the values from the second dict are ignored? Its reasonable and as I showed above has many use cases that would benefit the - and -= operator. If you would look at the examples above you would also notice that this operator works great combined with the |= existing operator (for example feature |= cfeature - feature).