Python output questions usually probe three behaviours: references, slicing and mutability. The syntax is short, which makes it tempting to answer from instinct. A better method is to mark which names share an object, which operations create a new object and which operations mutate one in place.
Here are 13 focused snippets. Predict each output before reading the explanation.
Lists and references
1. Two names, one list
a = [1, 2]
b = a
b.append(3)
print(a, b)Output:
[1, 2, 3] [1, 2, 3]Assignment does not copy the list. Both names refer to the same object, so an append through b is visible through a.
2. Shallow copy versus deep copy
import copy
a = [[1], [2]]
b = copy.copy(a)
c = copy.deepcopy(a)
a[0].append(9)
print(b, c)Output:
[[1, 9], [2]] [[1], [2]]The shallow copy creates a new outer list but shares the inner lists. The deep copy recursively creates independent nested objects, so c does not see the append.
3. List multiplication trap
grid = [[0] * 3] * 2
grid[0][1] = 7
print(grid)Output:
[[0, 7, 0], [0, 7, 0]]Multiplication repeats references to one inner list, not two independent rows. A safe construction is [[0] * 3 for _ in range(2)].
4. append versus extend
x = [1, 2]
y = [1, 2]
x.append([3, 4])
y.extend([3, 4])
print(x)
print(y)Output:
[1, 2, [3, 4]]
[1, 2, 3, 4]append adds its argument as one new element. extend iterates over its argument and adds each element separately.
![Reference diagram for snippet 1 showing names a and b pointing to the same list object [1, 2, 3], contrasted with c = a[:] pointing to a separate outer list object [1, 2, 3].](https://kgai.blob.core.windows.net/blog-assets/blog_asset_1784038511372_sj9pyy.jpg)
Slicing output questions
5. Negative indices
a = [10, 20, 30, 40]
print(a[-1], a[-3])Output:
40 20Index -1 selects the last element. Counting backwards, -3 selects 20.
6. A positive step
a = list(range(8))
print(a[1:7:2])Output:
[1, 3, 5]The slice starts at index 1 and stops before index 7. A step of 2 selects indices 1, 3 and 5.
7. Slice assignment can change length
a = [1, 2, 3, 4]
a[1:3] = [8, 9, 10]
print(a)Output:
[1, 8, 9, 10, 4]The target slice contains 2 and 3, and both are replaced. The replacement iterable has three elements, so the list grows by one.
8. Reversing with a slice
s = "gate"
print(s[::-1])Output:
etagOmitted bounds cover the full string, while a step of -1 walks backwards. The result is a new string because strings are immutable.
Mutability and function defaults
9. Mutable default argument
def add(value, bucket=[]):
bucket.append(value)
return bucket
print(add(1))
print(add(2))Output:
[1]
[1, 2]The default list is created once when the function is defined, not on every call. Use None as the default and create a new list inside when each call needs fresh state.
10. An immutable tuple can contain a mutable list
t = ([1, 2], "ok")
t[0].append(3)
print(t)Output:
([1, 2, 3], 'ok')Tuple immutability prevents rebinding a tuple position. It does not freeze a mutable object already referenced from that position.
11. String methods return new strings
s = "gate"
t = s.upper()
print(s, t)Output:
gate GATEupper() cannot modify s because strings are immutable. It returns a new string, which is bound to t.
is, == and the small-integer sting
12. Equality versus identity
a = [1, 2]
b = [1, 2]
c = a
print(a == b, a is b, a is c)Output:
True False True== compares values, so the two separately created lists are equal. is compares object identity, so only c, which was assigned from a, is identical to a.
13. Do not rely on integer caching
a = 256
b = a
print(a == b, a is b)Output:
True TrueThis result is guaranteed here because b is explicitly bound to the same object as a. If an exam instead creates equal integers independently and asks about a is b, the identity result can depend on the Python implementation, compilation context and integer caching; only a == b is the portable value test.
Well-written questions either state the implementation, use an explicit alias as above, or ask which operator is semantically correct. In production code, use is for singletons such as None, and == for numeric or container values.
How tests and vivas use these patterns
Placement tests compress these ideas into a few lines and ask for the exact output. Vivas usually follow with “why?”, which is where words such as alias, shallow copy, mutable and identity matter. The broader Coding and CS fundamentals guide helps connect these snippets to interview preparation, and Data Structures MCQs adds practice in representation and operation costs.
KnowledgeGate has about 480 published Python questions. Use the Python programming course to build the concepts in sequence, then return to output questions without running them first.
The short version
When checking an answer, name the object that changed and whether the operation mutated it or created a new one. The next time you see a short snippet, draw names and objects before tracing statements.
Use a three-column rough trace if the code is dense: statement, names-to-objects, and visible value. This separates rebinding from mutation and prevents a later print call from being evaluated against an earlier state.
Run the snippet only after committing your prediction, then explain any mismatch before moving on.
Start from the CS Fundamentals category, practise one group at a time, and explain each answer in one sentence about reference sharing or object creation. That is the habit output questions are testing.
