When the following code, which attaches an else clause to a for statement, is run, what is printed?
for n in range(4): if n == 9: breakelse: print("done")print(n)
Only 3 is printed, and done does not appear
Only done is printed, and 3 does not appear
3 and done are printed in this order
done and 3 are printed in this order
AnswerD. done and 3 are printed in this order
An else clause attached to a for statement runs when the loop finishes without being broken by break. There is no 9 in range(4), so break never happens, and after running the loop to the end, the print in else runs, so done appears. The following print(n) then prints the value left in n after leaving the loop, the last value, 3. Getting the order backward gives a form where 3 comes first; misunderstanding that else is always skipped at the end of a loop gives a form with no done; and overlooking that n remains after leaving the loop gives a form with no 3.
Q2 | break and else
Check how the else clause is treated when a loop is exited with break. What is the output of the following code?
for c in "abc": if c == "b": break print(c)else: print("no break")
a b c and no break are all printed
a and no break are printed in this order
a and b, the two of them, are printed in this order
a is printed, and no break is not printed
AnswerD. a is printed, and no break is not printed
On the first pass, c is a, so print(c) runs and a comes out. On the second pass, c becomes b, and break cuts the loop off. A for statement's else clause is only run when the loop finishes without being broken by break, so it is skipped here and no break does not appear. Assuming else always runs when the loop ends gives a form where no break also appears; misreading it as if print(c) came before the break gives a form where b also appears; and overlooking break itself gives a form where a b c are all printed.
Q3 | else even when empty
Consider what happens to a for statement's else clause when what it iterates over is empty. What is the result of running the following code?
items = []for it in items: print(it)else: print("finished")
The else clause is ignored and a TypeError occurs
Since there are 0 iterations, a StopIteration occurs
It exits the loop with nothing printed at all
finished is printed just once
AnswerD. finished is printed just once
The condition for a for statement's else clause to run is "the loop finished without being broken by break," not "it iterated at least once." Since items is empty, the body never runs, but since break did not happen either, else still runs as is, and finished is printed. If you think else is also skipped when it is empty, you get a form with nothing printed. Passing an empty list to a for statement is itself correct syntax, so it does not raise an exception, and neither TypeError nor StopIteration is raised.
Q4 | while/else
Consider attaching an else clause to a while statement and breaking out midway. What is the output of the following code?
n = 5while n > 0: n -= 1 if n == 2: breakelse: print("loop ended")print(n)
0 is printed, and loop ended is not printed
2 is printed, and loop ended is not printed
loop ended and 2 are printed in this order
loop ended and 0 are printed in this order
AnswerB. 2 is printed, and loop ended is not printed
n decreases by 1 from 5, going 4, 3, and then breaks once it reaches 2. A while statement's else clause, just like a for statement's, only runs when the loop finishes without being broken by break, so it is skipped here and loop ended does not appear. What is left is only the 2 from print(n). Thinking else always runs gives a form where loop ended also appears, and overlooking break and misreading it as looping until the condition becomes false gives a form where n becomes 0.
Q5 | continue
When the following code, which mixes continue and break in a single loop, is run, what list is finally printed?
out = []for i in range(6): if i == 3: continue if i == 5: break out.append(i)print(out)
[0, 1, 2, 4, 5]
[0, 1, 2, 3]
[0, 1, 2, 4]
[0, 1, 2, 3, 4]
AnswerC. [0, 1, 2, 4]
When i is 0, 1, or 2, both if statements are passed through and the value gets appended. When i is 3, continue kicks in, skipping the rest of that pass, that is, the append. When i is 4, it is appended again, and when i is 5, break cuts the loop off, so no append happens. So the result is [0, 1, 2, 4]. Thinking the pass with break is also added gives a form lined up all the way to 5, and treating continue like pass gives a form where 3 remains.
Q6 | range in reverse
Consider the order produced when range is given a negative step. What is the output of the following code?
print(list(range(10, 0, -3)))
[9, 6, 3, 0]
[7, 4, 1, -2]
[10, 7, 4, 1, 0]
[10, 7, 4, 1]
AnswerD. [10, 7, 4, 1]
range(start, stop, step) starts from start, advances by step, and stops before reaching stop. Here, subtracting 3 repeatedly from 10 proceeds as 10, 7, 4, 1, and the next value, -2, is not adopted since it is 0 or below. Since the stop value 0 is not included, it does not end up as a sequence with 0 at the end. Misunderstanding that start is not included gives a form starting from 7, and thinking the counting starts one step before start gives a form starting from 9. The point that stop is not included is the same as when the step is positive.
Q7 | range's type
Which of the following correctly describes the object obtained by calling the built-in function range?
A generator-type object that becomes empty after being iterated once
A range-type object that becomes a list when passed to list()
A tuple-type object whose elements cannot be replaced
A list-type object that is displayed as is with square brackets
AnswerB. A range-type object that becomes a list when passed to list()
What range returns is a range-type object, which computes the needed integer each time it is asked. It does not hold every element up front the way a list does, so it does not consume memory even for a large range. To see the contents lined up, you pass it through list(). type(range(3)) is range, not list or tuple, and simply displaying it does not show the sequence of elements but instead shows range(0, 3). It is also not a generator, since it is not single-use and can be iterated any number of times. Note that the property of being readable by index and not allowing elements to be replaced is the same as a tuple's, so that property alone cannot distinguish it from a tuple.
Q8 | Short-circuit evaluation
Check what the logical operators or and and return. What is the output of the following code?
print([] or 0 or "z")print(1 and 0 and 2)
True and False are printed in this order
False and 0 are printed in this order
z and 0 are printed in this order
z and 2 are printed in this order
AnswerC. z and 0 are printed in this order
or evaluates from the left and returns the first value that becomes true as is. Since an empty list and 0 are both false, the last one, "z", is returned. and, conversely, returns the first value that becomes false, so 1 is true, then at the next value, 0, false is settled and 0 is returned, and the rightmost 2 is never evaluated. What is returned is not a Boolean but the value at the point evaluation stopped, so True or False never comes out. and returning the rightmost 2 only happens when everything along the way was true.
Q9 | Chained comparison
When the following code, which combines a chained comparison with a ternary expression, is run, what is printed?
x = 3print(1 < x < 5)print("yes" if x % 2 else "no")
True and yes are printed in this order
True and no are printed in this order
False and no are printed in this order
False and yes are printed in this order
AnswerA. True and yes are printed in this order
1 < x < 5 means the same thing as (1 < x) and (x < 5); if x is 3, both hold, so it is True. A ternary expression is arranged as value-if-true if condition else value-if-false, and here the condition is x % 2, that is, 1. In Python, any nonzero integer is treated as true, so yes is chosen. Misreading the chained comparison as binding from the back, as in 1 < (x < 5), leads to the wrong answer that x < 5 is True, that is, 1, and then 1 < 1 is False. Also, thinking of 1 as false leads to choosing no.
Q10 | The role of pass
Which of the following correctly describes Python's pass statement?
It indicates cutting off the loop itself and exiting it
It indicates doing nothing, in a place where a block is syntactically required
It indicates skipping the rest of a loop and moving on to the next iteration
It indicates that the function has finished running and returns a value to the caller
AnswerB. It indicates doing nothing, in a place where a block is syntactically required
Because Python represents a block with indentation, you cannot write an empty block. pass is what fills that spot, for times when you plan to write the contents of a class or function later, or when you deliberately want to do nothing when a condition is met. It has no effect on the flow of execution. Moving on to the next iteration is continue, cutting off the loop is break, and returning a value to the caller is return — each plays a different role from pass.
Q11 | enumerate
When the following code, which passes a second argument to enumerate, is run, what appears on the screen?
for i, name in enumerate(["gu", "choki", "pa"], 1): print(i, name)
The 3 lines 1 gu / 2 choki / 3 pa are printed
The 3 lines 0 gu / 1 choki / 2 pa are printed
The 3 lines gu 1 / choki 2 / pa 3 are printed
Only the 2 lines 1 gu / 2 choki are printed
AnswerA. The 3 lines 1 gu / 2 choki / 3 pa are printed
enumerate returns (number, element) tuples in order, and the second argument, start, lets you specify the value to start counting from. Here, 1 is passed, so the numbers become 1, 2, 3. Confusing this with the default starting at 0 when start is omitted gives a form starting from 0. Because the returned tuple has the number first and the element second, the order of print(i, name) follows the same order too, so the name never comes out first. All 3 elements are taken out, so it is not cut off after 2 lines either.
Q12 | zip's length
Two lists of different lengths were passed to zip. What is the result of running the following code?
print(list(zip([1, 2, 3], [10, 20])))
[(1, 10), (2, 20)]
[(1, 10), (2, 20), (3,)]
[(1, 10), (2, 20), (3, 0)]
[(10, 1), (20, 2)]
AnswerA. [(1, 10), (2, 20)]
zip takes one element at a time from each of the iterables it is given, pairs them up, and stops as soon as the shortest one runs out. Here, the second list has 2 elements, so only 2 pairs are made, and the leftover 3 is silently dropped. It does not raise an error, nor is the shortfall padded with 0, nor is a tuple with only one element created. The contents of each pair are in the order they were passed, so they are not swapped the way 10 and 1 would be.
Q13 | Unzipping with zip
Paired data was re-passed to zip with a star. What is the output of the following code?
AnswerB. (1, 2, 3) is printed, followed by ('a', 'b', 'c')
Attaching a star passes each pair inside the list to zip as a separate argument. That is, it is the same as calling zip((1, 'a'), (2, 'b'), (3, 'c')), and the first elements of each pair are gathered together, and the second elements together, splitting into the two sequences (1, 2, 3) and ('a', 'b', 'c'). This is the standard trick for turning paired data back into its original two sequences, and passing it through zip twice returns you to the original. What is returned is tuples, not lists, so it does not come out in square-bracket form. If you forget the star and write zip(pairs), each pair itself is passed as a single argument, and you get a form lined up as one-element tuples, like ((1, 'a'),).
Q14 | dict and zip
A dictionary is built from a sequence of keys and a sequence of values. What is the result of running the following code?
zip(keys, vals) returns (key, value) tuples in order, and dict() takes that sequence of pairs and builds a dictionary from it. The first item of each pair becomes the key and the second the value, so it does not come out with the numbers as keys. Since it is passed through dict(), it does not stay as a list of tuples either. Even though it is displayed with curly braces, what makes something a dictionary is having pairs joined by a colon; just having values lined up would be a set.
Q15 | List comprehension
When the following code, which uses a list comprehension, is run, what list is printed?
print([n * n for n in range(1, 5)])
[0, 1, 4, 9]
[2, 4, 6, 8]
[1, 4, 9, 16]
[1, 4, 9, 16, 25]
AnswerC. [1, 4, 9, 16]
range(1, 5) returns 1, 2, 3, 4; the stop value 5 that was specified is not included. Squaring each gives 1, 4, 9, 16. Assuming range starts at 0 gives a sequence starting from 0, and misunderstanding that stop is included gives a sequence going up to 25. Misreading n * n as n * 2 gives a sequence increasing by 2 each time. It is worth building the habit of reading a comprehension as evaluating the leftmost expression for each element and building a new list from the results.
Q16 | Dictionary comprehension
Run a comprehension that has a colon inside curly braces. What is the output of the following code?
words = ["sun", "moon"]print({w: len(w) for w in words})
{'sun': 3, 'moon': 4}
[('sun', 3), ('moon', 4)]
{3: 'sun', 4: 'moon'}
{'sun', 'moon', 3, 4}
AnswerA. {'sun': 3, 'moon': 4}
A comprehension with a colon inside curly braces is a dictionary comprehension, where the left of the colon becomes the key and the right becomes the value. Here it produces a dictionary with each word as the key and its character count as the value. Reading the key and value swapped would give a dictionary with the character count as the key. Enclosing it in square brackets would give a list of tuples, but here it is curly braces, so that does not happen. Without a colon it would be a set comprehension and come out as just a display of lined-up values, but since there is a colon, what results is a dictionary.
Q17 | The type from parentheses
Something that looks like a comprehension was enclosed in parentheses. What type is displayed when the following code is run?
g = (n for n in range(3))print(type(g))
<class 'range'>
<class 'list'>
<class 'generator'>
<class 'tuple'>
AnswerC. <class 'generator'>
There is no such thing in Python as a tuple comprehension, and this form, enclosed in parentheses, becomes a generator expression instead. Its type is generator; rather than creating every value up front, it computes them one at a time as they are requested, so it saves memory, but since it is an iterator, it is exhausted after being used once. When you want a tuple, you wrap it with tuple(). Writing it with square brackets instead makes it a list comprehension, giving a list, and assigning range(3) directly gives a range. tuple is not obtained from this form of writing.
Q18 | Set comprehension
Count the number of elements in the container made by a set comprehension. What is the output of the following code?
print(len({n % 4 for n in range(10)}))
3 is printed
0 is printed
10 is printed
4 is printed
AnswerD. 4 is printed
Each value of range(10) divided by 4 leaves a remainder of 0, 1, 2, 3, 0, 1, 2, 3, 0, 1. A comprehension with curly braces and no colon is a set comprehension, so duplicate values are collected into one, and what remains is the 4 distinct values, 0, 1, 2, 3. Overlooking that duplicates disappear and simply counting the number of values gives 10. Overlooking that 0 is included among the remainders and counting only 1, 2, 3 gives 3. 0 is the value if you misunderstand that the comprehension produces nothing at all, but as long as it goes through range(10), the contents are never empty. The display order of a set is not fixed, so checking by the number of elements is the reliable way.
Q19 | A nested comprehension
Consider the ordering when two for clauses are lined up in a comprehension. What is the result of running the following code?
print([(x, y) for x in [1, 2] for y in "ab"])
[(1, 'a'), (2, 'b'), (1, 'b'), (2, 'a')]
[('a', 1), ('b', 1), ('a', 2), ('b', 2)]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
[(1, 'a'), (2, 'a'), (1, 'b'), (2, 'b')]
AnswerC. [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
When a comprehension has two for clauses lined up, the one written on the left becomes the outer loop. This is exactly the same order as writing a nested pair of ordinary for statements: x is fixed at 1 while y cycles through a and b, and then x becomes 2 and the same thing repeats. Reading the for clause on the right as the outer one gives an order where x cycles first. The contents of each pair follow the order written in the expression, (x, y), so the letter never comes first.
Q20 | The start argument
Which of the following correctly describes the start argument, the second argument of the built-in function enumerate?
It specifies the number to start counting from; omitting it counts from 0
It specifies which element to start taking from; omitting it starts from the beginning
It specifies how many to skip each time; omitting it advances one at a time
It specifies how many to count up to; omitting it counts to the end
AnswerA. It specifies the number to start counting from; omitting it counts from 0
The second argument of enumerate, start, only decides what number to start attaching from. The default is 0, so passing 1 gives a human-friendly running count. Only how the numbers are attached changes; the crucial point is that the range and count of the elements taken out do not change. It has no effect of limiting or skipping the count, nor does it shift the starting position of extraction. All of these describe other tools, such as slicing, instead.
Q21 | sort's return value
The return value of a list's sort method was captured in a variable. What is the output of the following code?
AnswerD. None and [3, 5, 9] are printed in this order
sort is a method that sorts a list in place, and its return value is None. So result holds None, and the sorted result remains in nums instead. If you assume a new sorted list is returned, you get a form where result holds a list. Overlooking that sort changes the original list gives a form where nums stays in its original order. When you want the sorted list while keeping the original, use the built-in function sorted.
Q22 | The difference with sorted
Which of the following correctly describes the difference between a list's sort method and the built-in function sorted?
sort returns a new list, and sorted sorts in place and returns None
sort sorts in place and returns None, and sorted returns a new list
Both return a new list, and neither original list changes
Both sort in place and also return the sorted list
AnswerB. sort sorts in place and returns None, and sorted returns a new list
sort is a list method, and it sorts that list itself, returning None as its return value. sorted is a built-in function, and it returns a new sorted list without changing the original order at all. Which to choose depends on whether you want to keep the original. Swapping the roles of the two around gives an explanation where sort returns a new list. Leaning toward one side or the other on whether it is destructive gives an explanation where both sort in place, or where neither changes the original. Note that sorted can also take an iterable other than a list, and its result is always a list.
Q23 | The difference with append
Compare two ways of adding one list to another. What is the output of the following code?
a = [1, 2]a.append([3, 4])b = [1, 2]b.extend([3, 4])print(a, b)
[1, 2, [3, 4]] [1, 2, [3, 4]]
[1, 2, 3, 4] [1, 2, [3, 4]]
[1, 2, 3, 4] [1, 2, 3, 4]
[1, 2, [3, 4]] [1, 2, 3, 4]
AnswerD. [1, 2, [3, 4]] [1, 2, 3, 4]
append adds its argument as a single whole element at the end, so if you pass a list, it becomes nested and the length increases by 1. extend adds the values obtained by iterating over its argument, one at a time, so the contents unpack and the length increases by 2. Swapping the two roles reverses the results for a and b. Assuming both do the same thing gives either a form where both nest or a form where both flatten out. Both methods also have None as their return value, so it is worth remembering not to capture the result in a variable.
Q24 | Shallow copy
A nested list was duplicated with a slice, and the inner part was rewritten. What is the result of running the following code?
Duplication by slicing is a shallow copy: the outer list is newly created, but the elements inside it are shared with the same objects as the original. copy1[0] and orig[0] point to the same list, so appending to it also shows up on the original side. If you assume it is completely separated, you get a form where the original does not change. Only the first inner list was rewritten, so it does not extend to the later element, and nothing was added to the outer list, so 9 does not end up lined up in the outer list either. To separate even the inner parts, use copy.deepcopy.
Q25 | Deep copy
Compare deep copy and shallow copy in a single piece of code. What does base become after it runs?
copy.deepcopy duplicates all the way down into the nested contents, so d[0] becomes a separate list from base[0], and appending to it does not reach base. Meanwhile, s is a shallow copy, so s[1] and base[1] are the same list, and appending to it does show up in base too. So only the later element gets extended. Assuming both reach base gives a form where both of the inner lists get extended, and assuming neither reaches it gives a form left unchanged. Mixing up deep copy and shallow copy gives a form where only the earlier element gets extended.
Q26 | A pitfall of multiplication
An attempt was made to build a two-dimensional table with list multiplication. What is the result of running the following code?
grid = [[0] * 3] * 2grid[0][1] = 5print(grid)
[[0, 0, 0], [0, 5, 0]]
[[5, 0, 0], [5, 0, 0]]
[[0, 5, 0], [0, 0, 0]]
[[0, 5, 0], [0, 5, 0]]
AnswerD. [[0, 5, 0], [0, 5, 0]]
Multiplying on the outside does not create new rows; it just lines up two references to the same single list. grid[0] and grid[1] are the same object, so rewriting the position at index 1 in one shows up as the same position changing in the other too. If you think the rows are independent, you get a form where only one row changes. Since the position rewritten is index 1, it also does not become a form where the first position becomes 5. To make each row independent, write [[0] * 3 for _ in range(2)].
Q27 | A one-element tuple
Compare the type of a value just enclosed in parentheses with a value that has a trailing comma. What is the output of the following code?
x = (7)y = (7,)print(type(x).__name__, type(y).__name__)
int and int are printed in this order
tuple and tuple are printed in this order
tuple and int are printed in this order
int and tuple are printed in this order
AnswerD. int and tuple are printed in this order
What decides a tuple is not the parentheses but the comma. (7) is just an integer enclosed in parentheses to show precedence of computation, so its type is int, and only (7,), with a trailing comma, becomes a one-element tuple. If you assume enclosing something in parentheses makes it a tuple, you get a form where both become tuple; mixing up the two gives a form with the order reversed or a form where both are int. Note that the empty tuple is an exception and is written as (), with no comma.
Q28 | Contents of a tuple
An attempt was made to add an element to a list placed inside a tuple. What is the result of running the following code?
t = (1, [2, 3], 4)t[1].append(5)print(t)
A TypeError is raised
(1, [2, 3], 4, 5)
(1, [2, 3, 5], 4)
(1, [2, 3], 4)
AnswerC. (1, [2, 3, 5], 4)
What a tuple freezes is which object each slot points to, not the contents of what it points to. t[1] is a list, and that list itself is mutable, so you can append to it. Writing something like t[1] = [], which assigns to the tuple's slot itself, would raise TypeError, but here no slot is being replaced. Since what was added to is inside the list, the tuple's length neither increases nor stays completely unchanged.
Q29 | Slice assignment
A list of a different length was assigned to a slice of a list. What is the output of the following code?
x = [1, 2, 3, 4, 5]x[1:3] = [9]print(x)
[1, 9, 4, 5]
[1, 9, 3, 4, 5]
[1, 9, 9, 4, 5]
[1, 2, 9, 4, 5]
AnswerA. [1, 9, 4, 5]
Assigning to a slice is an operation that replaces the entire specified range with the contents of the right-hand side. x[1:3] refers to the 2 elements 2 and 3, so those are replaced by the single element 9, and the overall length shrinks from 5 to 4. If you think only one element is replaced, you get a form where the length stays 5, and if you think the right-hand side is stretched to fit the width, you get a form where two 9's line up. Shifting the start of the range by one and reading it that way gives a form where the 2 remains. The point that the width of the left-hand side and the length of the right-hand side can differ is the characteristic of slice assignment.
Q30 | Insertion and deletion
A zero-width slice assignment and a del are performed one after the other. What is the result of running the following code?
y = [1, 2, 3]y[1:1] = [7, 8]del y[0]print(y)
[7, 8, 3]
[1, 7, 8, 3]
[7, 8, 2, 3]
[2, 3, 7, 8]
AnswerC. [7, 8, 2, 3]
y[1:1] is a zero-width range, so an assignment to it becomes an insertion with no accompanying removal, and the list becomes [1, 7, 8, 2, 3]. The following del y[0] removes the leading 1, leaving [7, 8, 2, 3]. If you read it as if one of the original elements also disappears during the insertion, you get the form 7 8 3, and if you think del removes a different position, you get a form where the leading 1 remains. Misreading it as if the values were appended at the end gives a form where 2 and 3 come first. It is also worth keeping in mind that del is a statement, so it has no return value, and it removes without extracting the value either.
Q31 | get's default value
A key that is not in the dictionary was looked up with get. What is printed when the following code is run?
d = {"a": 1, "b": 2}print(d.get("z"), d.get("z", 0))
None and 0 are printed in this order
A KeyError is raised at the first one
None and None are printed in this order
0 and 0 are printed in this order
AnswerA. None and 0 are printed in this order
get does not raise an exception when a key is missing; it returns None if the second argument is omitted, or that value if it is given. So the first is None, and the second is 0. If you think 0 is returned even when there is no second argument, you get both as 0, and if you think the second argument is ignored, you get both as None. Writing d["z"] with square brackets would give a KeyError, and get is the tool for avoiding that.
Q32 | setdefault
setdefault was called for both a key that already exists and one that does not. What is the output of the following code?
d = {"a": 1}print(d.setdefault("a", 99))print(d.setdefault("b", 99))print(d)
99 and 99 are printed, followed by {'a': 99, 'b': 99}
1 and 99 are printed, followed by {'a': 1, 'b': 99}
1 and None are printed, followed by {'a': 1, 'b': None}
1 and 99 are printed, followed by {'a': 1}
AnswerB. 1 and 99 are printed, followed by {'a': 1, 'b': 99}
setdefault just returns the existing value if the key is present, without changing the dictionary. If the key is missing, it inserts the second argument as the value and returns that value. So the first call returns the existing 1 and the dictionary stays as is, and the second call inserts 99 and returns 99. If you think even the existing value gets overwritten, you get both as 99, and if you think no insertion happens, you get a form where the dictionary does not grow. Omitting the second argument makes the value inserted None, so a form with None inserted is the result of not writing the second argument.
Q33 | What in looks at
Check what the in operator examines for a dictionary. What is the output of the following code?
d = {"x": 1, "y": 2}print("x" in d, 1 in d, 1 in d.values())
True False True is printed in this order
True True True is printed in this order
True False False is printed in this order
False True True is printed in this order
AnswerA. True False True is printed in this order
in on a dictionary only checks the keys. "x" is a key, so it is True; 1 exists as a value but is not a key, so it is False. When you want to check the values, target d.values() instead, which comes out True here. If you think in also looks at values, everything becomes True, and if you think values() also does not look at values, the last one becomes False. Swapping the roles of key and value gives a form where the first is False. Checking whether a key exists before looking it up with square brackets is the standard usage.
Q34 | Duplicate keys
The same key was written twice in a dictionary literal. What is the result of running the following code?
d = {"a": 1, "b": 2, "a": 3}print(d)
{'a': 3, 'b': 2}
{'a': 1, 'b': 2}
{'b': 2, 'a': 3}
{'a': 3, 'b': 3}
AnswerA. {'a': 3, 'b': 2}
A dictionary literal builds its entries in order from left to right, so if the same key appears twice, the later value overwrites the earlier one. It does not become an error or a warning. If you think the one written first remains, you get a value of 1 for a. Also, a dictionary preserves insertion order, and an overwrite does not move the position, so a stays in the position it came first. So the order of the keys is not swapped either, nor does the value of b change as a side effect.
Q35 | Ways of building a dictionary
Compare a dictionary built from keyword arguments with one built from a sequence of pairs. What is the output of the following code?
AnswerC. True is printed, followed by {'x': 1, 'y': 2}
dict can build a dictionary both from keyword arguments and from a sequence of (key, value) pairs. Either way of writing it produces a dictionary with the same content, so the comparison is True. If you think a different way of building it produces something different, the comparison becomes False. The name of a keyword argument becomes the key string as is, so key and value are never swapped. Once it has been passed through dict, it is already a dictionary, so it does not stay as a sequence of pairs either.
Q36 | Empty curly braces
Compare the type of empty curly braces with that of set(). What are the two type names displayed when the following code is run?
a = {}b = set()print(type(a).__name__, type(b).__name__)
dict and dict are printed in this order
set and set are printed in this order
dict and set are printed in this order
set and dict are printed in this order
AnswerC. dict and set are printed in this order
{1, 2}, which has elements in it, becomes a set, but when it is empty, it cannot be decided whether it is a dictionary or a set. Python treats this case as a dictionary, so {} is an empty dictionary. When you want an empty set, you have no choice but to write set(). If you think curly braces always mean a set, you get both as set, and mixing up the two gives the order reversed. Thinking even set() becomes a dictionary gives both as dict. Since both sets and dictionaries use curly braces, this distinction is easy to mix up.
Q37 | Set operations
An intersection and a symmetric difference were performed on two sets. What is the output of the following code?
[3, 4] and [1, 2, 3, 4, 5] are printed in this order
[1, 2, 5] and [3, 4] are printed in this order
[3, 4] and [1, 2] are printed in this order
[3, 4] and [1, 2, 5] are printed in this order
AnswerD. [3, 4] and [1, 2, 5] are printed in this order
The ampersand is intersection, so 3 and 4, which are in both, remain. The caret is symmetric difference, and it gathers elements that are in only one or the other, so 1 and 2, which are only in s1, and 5, which is only in s2, remain, while the common 3 and 4 drop out. Mixing up symmetric difference with difference gives a form with 5 dropped out, and swapping the two operations reverses the order of the output. Mixing up symmetric difference with union gives a form that also includes 3 and 4. The display order of a set is not fixed, so here it is confirmed by lining the results up with sorted.
Q38 | Removing duplicates
A list with duplicates was passed through a set. What is the output when the following code is run?
data = [3, 1, 3, 2, 1, 1]print(len(set(data)), sorted(set(data)))
6 and [3, 1, 3, 2, 1, 1] are printed in this order
6 and [1, 2, 3] are printed in this order
3 and [3, 1, 2] are printed in this order
3 and [1, 2, 3] are printed in this order
AnswerD. 3 and [1, 2, 3] are printed in this order
Passing a list to set removes duplicates, leaving the 3 distinct values 1, 2, 3, so the length is 3. Passing a set to sorted returns a new list sorted in ascending order. If you think the duplicates remain, you get a count of 6. sorted arranges by size, not by original order of appearance, so it is not lined up in first-seen order either. A set's own display order carries no meaning, so pass it through sorted when you want it ordered.
Q39 | A condition on elements
An attempt was made to add a tuple and then a list to a set, one after the other. What happens when the following code is run?
s = set()s.add((1, 2))s.add([3, 4])print(len(s))
1 is printed, and the list is converted into a tuple
A TypeError is raised, because a list cannot be put into a set
A ValueError is raised, because element types cannot be mixed
2 is printed, and both elements go into the set
AnswerB. A TypeError is raised, because a list cannot be put into a set
A set's elements, and a dictionary's keys, must be hashable. A tuple cannot have its contents changed, so it is hashable and can be added, but a list can have its contents change later, so it is not hashable, and it becomes a TypeError with a message about an unhashable type. Assuming both go in gives an output of 2, and assuming it gets implicitly converted to a tuple gives an output of 1. Mixing types is not itself a problem, so the reasoning that it would become a ValueError is also wrong.
Q40 | Three ways of taking things out
Which combination is appropriate for what the dictionary methods keys, values, and items each return?
keys returns pairs of values, values returns pairs of keys, and items returns the item count
keys returns pairs of keys and values, values returns keys, and items returns values
keys returns values, values returns keys, and items returns pairs of values
keys returns keys, values returns values, and items returns pairs of keys and values
AnswerD. keys returns keys, values returns values, and items returns pairs of keys and values
keys returns only the keys, values returns only the values, and items returns (key, value) tuples in order. The standard pattern when iterating over a dictionary is to receive two variables, as in for k, v in d.items(). Swapping the roles of the three around gives explanations such as keys returning values. What items returns is a sequence of items, not a count, so the explanation that it returns the item count is also wrong; use len when you want to know the count. Note that passing the dictionary itself directly to for extracts the keys.
Practice: answer the questions on this page
This practice tool asks questions in random order (it works when JavaScript is enabled). You can still read all the questions and explanations above without it.
* The explanations are information for study purposes. Exam scope and systems change from year to year, so always check the official announcements of the organization that administers the exam.
This page is a translation of the Japanese original. If the translation and the original differ, the Japanese version takes precedence. View the Japanese original