Interviewers love Python gotchas: short snippets where the obvious answer is wrong. They are not tricks for their own sake. Each one exposes a real rule about how Python works, and each one causes real bugs in real code. Below are seven of the most common, as “what does this print?” puzzles. Cover the answer, make your guess, then open it.
Every output on this page was produced by actually running the code, on more than one Python version.
In this guide
The seven at a glance
- A default argument like
[]is created once and shared between calls. - A lambda looks up a loop variable when it is called, not when it is made.
list.sort()sorts in place and returnsNone.sorted()returns a new list.True == 1 == 1.0and they hash the same, so they collide as keys.round()rounds halves to the nearest even number, and//rounds toward minus infinity.t[0] += xon a tuple holding a list mutates the list and then raises an error.==compares values.iscompares identity. UseisforNone.
1. Mutable default argument
Gotcha 1: The list that remembers
What does this print?
def add_tag(tag, tags=[]):
tags.append(tag)
return tags
print(add_tag("a"))
print(add_tag("b"))
Show the output and the explanation
Output
['a']
['a', 'b']The default [] is created once, when the function is defined, and every call that does not pass tags shares that one list. The second call finds 'a' still in it.
The fix: use None as the default and create a fresh list inside the function.
def add_tag(tag, tags=None):
if tags is None:
tags = []
tags.append(tag)
return tags
print(add_tag("a"))
print(add_tag("b"))
Output
['a']
['b']More in Python Functions: Arguments, Return and Scope.
2. Late-binding lambdas in a loop
Gotcha 2: Every function returns 2
What does this print?
funcs = []
for i in range(3):
funcs.append(lambda: i)
print([f() for f in funcs])
Show the output and the explanation
Output
[2, 2, 2]A lambda does not capture the value of i. It captures the variable itself, and looks up its value when called. By then the loop has finished and i is 2, so all three lambdas return 2.
The fix: bind the current value with a default argument, lambda i=i: i.
funcs = []
for i in range(3):
funcs.append(lambda i=i: i)
print([f() for f in funcs])
Output
[0, 1, 2]See Python lambda, map, filter and reduce Explained.
3. list.sort() returns None
Gotcha 3: The vanishing list
What does this print?
nums = [3, 1, 2]
result = nums.sort()
print(result)
print(nums)
print(sorted([3, 1, 2]))
Show the output and the explanation
Output
None
[1, 2, 3]
[1, 2, 3]Methods that change a list in place, such as sort(), append() and reverse(), return None so you do not mistake them for functions that return a new list. Writing nums = nums.sort() replaces your list with None. Use sorted(nums) when you want a new sorted list.
4. True, 1 and 1.0 are the same dictionary key
Gotcha 4: Three keys become one
What does this print?
d = {1: "int", True: "bool", 1.0: "float"}
print(d)
print(len(d))
print(sum([True, False, True]))
Show the output and the explanation
Output
{1: 'float'}
1
2True == 1 == 1.0 is true, and they have the same hash, so a dictionary treats them as one key. The first key object (1) stays, and the last value ('float') wins. This works because bool is a subclass of int, which is also why sum([True, False, True]) is 2.
Related: Python Data Types Explained With Examples.
5. round() and negative division
Gotcha 5: Banker’s rounding and floor division
What does this print?
print(round(0.5), round(1.5), round(2.5), round(3.5))
print(-7 // 2, -7 % 3)
print(int(-3.9))
Show the output and the explanation
Output
0 2 2 4
-4 2
-3Python’s round() rounds exact halves to the nearest even number (0.5 becomes 0, 2.5 becomes 2), so that errors do not pile up in one direction. // is floor division: it rounds toward minus infinity, so -7 // 2 is -4, not -3. The remainder % follows, so -7 % 3 is 2. And int() simply cuts off the decimals (toward zero), so int(-3.9) is -3.
6. A tuple that raises an error and changes anyway
Gotcha 6: The error that did not stop the change
What does this print?
t = ([1, 2], 3)
try:
t[0] += [3]
except TypeError as e:
print(type(e).__name__)
print(t)
Show the output and the explanation
Output
TypeError
([1, 2, 3], 3)t[0] += [3] works in two steps. First, the list at t[0] is extended in place, which succeeds. Then Python tries to assign the result back into t[0], which a tuple forbids, so it raises TypeError. The damage from step one is already done. Lesson: a tuple is immutable, but the objects inside it may not be.
See Mutable vs Immutable Objects in Python.
7. is vs ==
Gotcha 7: Equal, but not the same
What does this print?
a = [1, 2]
b = [1, 2]
print(a == b, a is b)
c = a
print(c is a)
x = None
print(x is None, x == None)
Show the output and the explanation
Output
True False
True
True True== asks whether two objects have equal values. is asks whether they are the very same object. Two separate lists with the same contents are equal but not identical. Use is only for singletons such as None, True and False, and use == for everything else. Do not rely on is with numbers or strings: whether two equal ones happen to be the same object is an implementation detail.
Lightning round
Four more that come up often. Guess each line before you open the answer.
print("hehe_x".lstrip("he"))
grid = [[0] * 2] * 3
grid[0][0] = 1
print(grid[2][0])
def f():
try:
raise ValueError
finally:
return "swallowed"
print(f())
print(0.1 + 0.2 == 0.3)
Show the output and the explanation
Output
_x
1
swallowed
False"hehe_x".lstrip("he")gives_x:stripremoves any of the characters in the set, not a prefix.[[0] * 2] * 3repeats one row three times, so changing one row changes them all (the answer is 1).- A
returninsidefinallyoverrides the exception that was about to be raised, so it is swallowed. 0.1 + 0.2 == 0.3isFalsebecause of binary floating point. Usemath.isclose().
Test yourself
Three fresh ones. No hints.
A. print(type(1 / 2), type(1 // 2))
Show answer
Output
<class 'float'> <class 'int'>/ always gives a float, and // on two integers gives an integer.
B. What does x contain at the end?
x = [1, 2, 3]
y = x
y += [4]
print(x)
Show answer
Output
[1, 2, 3, 4]y = x makes a second name, and y += [4] extends the list in place, so x sees the change.
C. print(bool("False"), bool(""), bool([0]))
Show answer
Output
True False TrueTruthiness depends on emptiness, not on what the text says. A non-empty string and a non-empty list are both true.
Run any of them in our free Python compiler and change them to see what breaks.
Frequently asked questions
Why does Python have so many gotchas?
Most are consequences of a few consistent rules: variables are names for objects, some objects can change in place, and a function’s defaults and closures are evaluated at particular times. Learn those rules and the surprises stop being surprising.
What is the most common Python interview gotcha?
The mutable default argument. It appears in interviews constantly because it tests whether you understand when default values are created.
What is the difference between is and == in Python?
== compares values. is checks whether two names point to the same object. Use is for None and == for values.
What is the difference between sort() and sorted()?
list.sort() sorts the list in place and returns None. sorted(items) leaves the original alone and returns a new sorted list, and works on any iterable.
How can I avoid these bugs in real code?
Know the rules above, use a linter (many flag mutable defaults and comparisons to None), write small tests, and copy lists deliberately when you need an independent version.
Related reading
- Mutable vs Immutable Objects in Python – the idea behind gotchas 1, 6 and the grid.
- Shallow Copy vs Deep Copy in Python – copy data safely.
- Python Functions: Arguments, Return and Scope – defaults, scope and return values.
- Python Exception Handling: try, except, finally – why return in finally is dangerous.
Run this code in your browser
The free Upskly compiler runs Python with nothing to install. Paste the example, change it and see what happens.
Stuck on a traceback?
AI Assist works inside the Python notebook, so you can ask about an error or a concept without leaving the cell.
Test yourself
Timed questions on Python Interview Gotchas, with an explanation for every answer.