Tricky 20 Questions • ~4 hrs study

Output-Based Questions

Tricky Python output questions that test deep understanding — mutable defaults, closures, variable scope, floating point, and common gotchas.

1

What is the output?

def append_to(element, lst=[]):
    lst.append(element)
    return lst

print(append_to(1))
print(append_to(2))
print(append_to(3))

Answer

[1]
[1, 2]
[1, 2, 3]

Default mutable arguments are shared across calls. The list is created once when the function is defined, not each time it's called.

💡 Memory Trick: "Mutable defaults are born once, live forever — use None as default instead"

2

What is the output?

funcs = [lambda x: x + i for i in range(4)]
print([f(0) for f in funcs])

Answer

[3, 3, 3, 3]

Closures capture variables by reference, not value. All lambdas share the same i, which is 3 after the loop ends. Fix: use default argument lambda x, i=i: x + i.

💡 Memory Trick: "Lambda in loop = late binding trap. Fix with default arg to capture NOW"

3

What is the output?

x = [1, 2, 3]
y = x
y = y + [4]
print(x)
print(y)

Answer

[1, 2, 3]
[1, 2, 3, 4]

y = y + [4] creates a NEW list (rebinding). If it were y += [4] or y.extend([4]), it would modify x too since += calls __iadd__ which mutates in-place for lists.

💡 Memory Trick: "+ creates new | += mutates in-place (for mutable types)"

4

What is the output?

print(0.1 + 0.2 == 0.3)
print(round(0.1 + 0.2, 1) == 0.3)

Answer

False
True

Floating point representation: 0.1 + 0.2 = 0.30000000000000004. Use math.isclose() or decimal.Decimal for precise comparisons.

💡 Memory Trick: "Never == floats! Use math.isclose() or round()"

Questions 5-20 continue with the same tricky format.

Topics covered: String interning, is vs ==, generator exhaustion, tuple unpacking surprises, class variable mutation, decorator execution order, walrus operator edge cases, and more Python gotchas.

View Full Documentation →