Identity, mutation and copies
Predict each line before you run it. Then change nested[0].append(99) to nested[0] = [99] and see why shallow no longer changes.
The core-language questions that come up in almost every Python interview: mutability, is versus ==, default arguments, scope, copying, comprehensions and truthiness. For each one you get the precise answer and a program that proves it.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Predict the output, then run it: a = [1, 2]; b = a; b += [3]; c = a; c = c + [4]; print(a, b, c). Explain why += and + behave differently on lists.
Write unique_in_order(items) that returns the items with duplicates removed, keeping first-seen order, without using a default mutable argument.
Write a function make_counter() that returns a function; each call to the returned function gives 1, 2, 3, and so on, with no global variable.
Explain it without notes
What is the difference between is and ==? When is is the right operator?
Why is def f(x, items=[]) a bug, and what is the standard fix? When is a mutable default actually useful?
Explain shallow copy versus deep copy with an example where the difference changes the result.
Why does counter += 1 raise UnboundLocalError inside a function when counter exists at module level?
Python is sometimes called pass-by-value and sometimes pass-by-reference. What is the accurate description?
Why can a tuple be a dict key when a list cannot? Is every tuple usable as a key?
Is Python a compiled or an interpreted language?
Expected output
a == c: True | a is c: False | a is b: True
b sees the change: [1, 2, 3, 4]
c does not: [1, 2, 3]
shallow: [[1, 2, 99], [3]]
deep: [[1, 2], [3]]
TypeError: 'str' object does not support item assignment
tuple holding a list: (1, [2, 3, 4])
x is None: True | x == None: True