Semester 2, 2023 Exam
Question 1
What is stored in x after only the following code is executed by Python?
Pi = 3.14
x = 2 * 'Pi'
A. 6
B. 6.0
C. 6.18
D. 'PiPi'
E. None of the above
查看答案与解析
解析:
2 * 'Pi' 是字符串重复,不是数学乘法。
结果是 'PiPi'。
答案:D. 'PiPi'
Question 2
Which statement below is false?
A. We do not have to verify preconditions because it is the user's fault for breaking them.
B. Functions have a "local scope" which means we can use the same variable-name in different functions instead of having to use many unique variable-names.
C. A constant value in Python can be modified.
D. Python prohibits the modification of private variables and the only way to change one is with a getter.
E. None of the above
查看答案与解析
解析:
A 项错误。即使是用户破坏了前置条件,程序员也应当在代码中进行适当的校验。
B、C、D 虽然措辞有点问题,但只有 A 是明显错误。
答案:A. We do not have to verify preconditions because it is the user's fault for breaking them.
Question 3
What is stored in x after only the following code is executed by Python?
def foo(x: int, y: int) -> int:
if x > y:
z = x - y
elif x < y:
z = y - x
return z
x = foo(6, 6)
A. 0
B. 6
C. -6
D. Error
E. None of the above
查看答案与解析
解析:
x = 6, y = 6
既不满足 x > y,也不满足 x < y,所以 z 从未被赋值。
return z 时找不到 z,直接报错 UnboundLocalError。
答案:D. Error
Question 4
What does the following arithmetic expression evaluate to in Python?
2 ** 3 % 5 - 1
A. 0
B. 2
C. 4
D. 7
E. None of the above
查看答案与解析
解析:
运算顺序:
2 ** 3 = 8
8 % 5 = 3
3 - 1 = 2
答案:B. 2
Question 5
What is the value of xs after only the following is evaluated?
xs = (1, 2, 3)
ys = xs
ys[1] = 0
A. (0, 2, 3)
B. (1, 0, 3)
C. None
D. Error
E. None of the above
查看答案与解析
解析:
元组是不可变的(immutable)。
试图修改 ys[1] 会导致 TypeError。
答案:D. Error
Question 6
What is stored in x when only the following is executed by Python?
x = len("1\t2\t3")
A. 5
B. 7
C. 11
D. It depends on the number of spaces in a tab.
E. None of the above
查看答案与解析
解析:
字符串 "1\t2\t3" 实际有:数字 1、制表符\t、数字 2、制表符\t、数字 3
每个\t 算作 1 个字符,所以总长度是 5。
答案:A. 5
Question 7
What is the value of y after only the following has been executed?
y = 0
for x in range(5):
if x == 2 or 3 or 4 or 5:
y += 1
A. 2
B. 3
C. 4
D. 5
E. None of the above
查看答案与解析
解析:
if x == 2 or 3 or 4 or 5 实际理解为:(x == 2) or (3) or (4) or (5)
由于数字 3、4、5 在布尔上下文中为 True,所以条件永远为 True。
range(5)是 0 到 4,共 5 个数,全部满足条件,每次 y += 1。
所以最后 y = 5。
答案:D. 5
Question 8
How many of the following statements evaluate to True?
bool("False")
bool(" ") # 1 space
bool(False and True or True)
A. 0
B. 1
C. 2
D. 3
E. None of the above
查看答案与解析
解析:
分别判断:
bool("False"):非空字符串为 True ✅
bool(" "):空格字符串也是 True ✅
bool(False and True or True):False and True = False,然后 False or True = True ✅
三句都是 True。
答案:D. 3
Question 9
What is stored in y after only the following code is executed?
def foo(xs: str) -> str:
if xs:
return 2 * xs
y = foo("")
A. "" (empty string)
B. " " (one space)
C. " " (two spaces)
D. None
E. None of the above
查看答案与解析
解析:
传入 foo(""),xs 是空字符串,if xs: 条件不满足。
没有 return 语句,默认返回 None。
答案:D. None
Question 10
What is the appropriate type-hint for the following function, assuming the function contains valid code and can be called without generating an error?
def foo(x, y, z):
for z in y:
if x in z:
z.append(x)
return x * y[0] + z
A. foo(x: str, y: list[str], z: str) -> str
B. foo(x: int, y: list[list[int]], z: list[int]) -> list[int]
C. foo(x: int, y: list[str], z: str) -> None
D. foo(x: int, y: list[int], z: int) -> list[int]
E. None of the above
查看答案与解析
解析:
for z in y,说明 y 是可迭代的,每个元素 z 要能调用 append 方法。
只有 list 支持 append,所以 y 应该是 list[list[int]]。
x 在 z 里,x 应该是 int。
最后返回的是 list[int]。
答案:B. foo(x: int, y: list[list[int]], z: list[int]) -> list[int]
Question 11
Suppose we define a new class for hospital admissions. Which name is most appropriate for this class?
A. hospital_admissions
B. HOSPITAL_ADMISSIONS
C. HospitalAdmissions
D. hospital_admissions
E. None of the above
查看答案与解析
解析:
类名应采用驼峰命名法(PascalCase)。
HospitalAdmissions 符合类命名规范。
其他选项是变量命名风格或特殊方法命名风格。
答案:C. HospitalAdmissions
Question 12
What is the value of x after only the following code is run?
x = 0
def foo(x: int) -> int:
x = x + 1
foo(x)
foo(x)
A. 0
B. 1
C. 2
D. Error
E. None of the above
查看答案与解析
解析:
foo 函数修改的是局部变量 x,不会影响外部的全局变量 x。
所以调用 foo(x)两次后,外部的 x 仍然是初始值 0。
答案:A. 0
Question 13
The following is an incomplete recursive function that counts the number of times a given integer occurs in a given list.
def foo(xs: list[int], x: int) -> int:
""" >>> foo([10, 10, 20], 20)
1 >>> foo([10, 10, 20], 10)
2
"""
a, b = ?
if len(xs) == a:
return b
return (xs[0] == x) + foo(xs[1:])
What should be assigned to a, b at line 8 to make the function work?
A. 0, 0
B. 1, 1
C. 0, xs[0] == x
D. 1, xs[0] == x
E. None of the above
查看答案与解析
解析:
当列表长度为 0 时,应返回计数 0。
所以 (a, b) 应该是 (0, 0)。
注意:递归的 base case 是空列表。
答案:A. 0, 0
Question 14
What best describes the behaviour of the following function?
def foo(y, z):
for x in y:
if x > z:
return True
else:
return False
return False
A. Always returns True.
B. Always returns False.
C. Returns False only when there is no element of y that is strictly greater than z.
D. Returns True only when the first element of y is strictly greater than z.
E. None of the above
查看答案与解析
解析:
for 循环第一次迭代就会立即返回,无论 x > z 是否成立。
所以只取决于第一个元素是否大于 z。
答案:D. Returns True only when the first element of y is strictly greater than z.
Question 15
What is stored in x after running only the following code?
x = "drake is overrated".capitalize()
Given that capitalize() means:
- Make the first character uppercase
- Make the rest of the string lowercase
A. "Drake is overrated"
B. "Drake Is Overrated"
C. "DRAKE IS OVERRATED"
D. None
E. None of the above
查看答案与解析
解析:
.capitalize() 会使首字母大写,其余全部小写。
所以 "drake is overrated" 变为 "Drake is overrated"。
答案:A. "Drake is overrated"
Question 16
Suppose the following lines of Python have been executed.
letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
xs = letters[5:-5:1]
What is stored in xs?
A. ['F', 'E']
B. ['F', 'E', 'D']
C. []
D. Error
E. None of the above
查看答案与解析
解析:
切片 letters[5:-5:1],start=5,end=-5。
letters[5] 是 'F',letters[-5] 是 'C'。
因为 start > end,步长又是正的,所以返回空列表。
答案:C. []
Question 17
What type of error is thrown by executing the following code?
def foo(x: str, y: str) -> str:
""" >>> foo("Monty", "Python")
'MontyPython'
"""
return x + y
ans = foo(2, 1/3)
A. TypeError
B. NameError
C. ValueError
D. This is valid Python code.
E. None of the above
查看答案与解析
解析:
foo(2, 1/3):传入的是 int 和 float,而函数预期是 str。
在 return x + y 尝试字符串加法时,出现类型不匹配。
Python 抛出 TypeError。
答案:A. TypeError
Question 18
What is stored in x after only the following is executed?
x = (1) + (2) + (3)
A. (1, 2, 3)
B. (1, (2, 3))
C. ((1, 2), 3)
D. None of the above
E. None of the above
查看答案与解析
解析:
(1)、(2)、(3) 都是数字,不是元组。
(1) + (2) + (3) 实际是数值加法,1 + 2 + 3 = 6。
所以都不是给的选项。
答案:D. None of the above
Question 19
What is the behaviour of the following function, supposing it is called properly (i.e. preconditions are satisfied)?
def foo(xss: list[list[int]]) -> dict[list[int], int]:
""" Precondition: len(xss) > 0 """
ans = dict()
for xs in xss:
ans[xs] = sum(xs)
return ans
A. foo always returns None.
B. foo always raises an error.
C. foo returns a dictionary mapping lists to their sums.
D. foo has a logical error because many lists can have the same sum.
E. None of the above
查看答案与解析
解析:
列表(list)是不可哈希的,不能作为字典的 key。
ans[xs] = sum(xs) 会直接导致 TypeError。
答案:B. foo always raises an error.
Question 20
Which is not a Python naming convention/rule?
A. Class attributes that should not be changed by the user (i.e. private variables) start with an underscore _like_this.
B. Magic methods are surrounded by double underscore like_this.
C. Global constants are capitalized LIKE_THIS.
D. Class attributes are camel cased likeThis.
E. None of the above
查看答案与解析
解析:
A、B、C 都是正确的 Python 命名规则。
D 是错误的,类名用 PascalCase(LikeThis),而不是 camelCase(likeThis)。
答案:D. Class attributes are camel cased likeThis.
Question 21
What is the value of xs after executing the following?
ys = ["A", "B"]
xs = ["D"]
ys.extend(["C"])
xs.append(ys)
A. ["D", ["A", "B", "C"]]
B. ["D", "A", "B", "C"]
C. ["D", ["A", "B", ["C"]]]
D. Error
E. None of the above
查看答案与解析
解析:
ys = ["A", "B"]
ys.extend(["C"]) → ["A", "B", "C"]
xs = ["D"]
xs.append(ys) → 把整个 ys 作为一个元素添加到 xs,所以 ["D", ["A", "B", "C"]]
答案:A. ["D", ["A", "B", "C"]]
Question 22
What line of code should replace #sub in order to generate the window illustrated above?
import tkinter as tk
root = tk.Tk()
#sub
root.mainloop()
A. root.geometry("200x400")
B. root.geometry("200 x 400")
C. root.geometry("400x200")
D. root.geometry("400 x 200")
E. None of the above
查看答案与解析
解析:
tkinter.geometry()方法要求字符串格式 "宽 x 高",中间不能有空格。
"400x200"是合法的格式。
答案:C. root.geometry("400x200")
Question 23
Suppose we want to assign True to the name validate when a user has inputted only the single digit '1', '2', '3', or '4' (and False otherwise). Which proposition should replace #sub?
value = input("Enter a single digit: ")
validate = #sub
A. value == "1" or "2" or "3" or "4"
B. value in "1234"
C. "1" <= value <= "4"
D. int(value) in range(1, 5)
E. None of the above
查看答案与解析
解析:
A 错误:value == "1" or "2"这种写法总是 True。
B 正确:value in "1234"可以检查字符串是否是'1'、'2'、'3'、'4'之一。
C 错误:"1" <= value <= "4" 会出错,因为字符串比较不符合预期。
D 正确:int(value) in range(1,5)也能正确判断,不过如果输入不是数字会导致异常。
最稳妥的是 B。
答案:B. value in "1234"
Question 24
What exception should be used at <Error> to complete the function?
def foo() -> int:
"""
Prompts the user to enter an integer.
Repeats until a number is entered.
"""
try:
return int(input("Enter an integer "))
except <Error>:
return foo()
A. TypeError
B. ValueError
C. InputError
D. IntError
E. None of the above
查看答案与解析
解析:
如果输入不能被 int()转换,比如输入字母,会抛出 ValueError。
不是 TypeError,也没有 InputError 和 IntError 这类内置异常。
答案:B. ValueError
Question 25
Consider the following function.
def foo(xs: list[int], ys: dict) -> bool:
for x in xs:
if not x in [ys[k] for k in ys]:
return False
return True
A. foo always returns True.
B. foo always returns False.
C. foo returns True only when every element of xs is a key of ys.
D. foo returns True only when every element of xs is a value of ys.
E. None of the above
查看答案与解析
解析:
[ys[k] for k in ys] 是取字典所有的 value。
检查的是 x 是否在 ys 的 value 中。
所以:只有当 xs 中每个元素都出现在 ys 的 values 中时,返回 True。
答案:D. foo returns True only when every element of xs is a value of ys.
Question 26
The following tkinter window has been stretched using the mouse.
What line of code should replace #sub in order to generate the window illustrated above?
import tkinter as tk
root = tk.Tk()
label = tk.Label(text="Drizzy", background="black", foreground="white")
# sub
label.pack(expand=opts[0], fill=opts[1])
root.mainloop()
A. opts = Tk.TRUE, Tk.NONE
B. opts = Tk.FALSE, Tk.BOTH
C. opts = Tk.NONE, Tk.TRUE
D. opts = Tk.BOTH, Tk.FALSE
E. None of the above
查看答案与解析
解析:
窗口被拉伸,说明 fill=BOTH,且 expand=True。
A、B、C 中 opts 配的不对,只有 D 符合。
Tk.BOTH 让控件填充水平和垂直方向,expand=False 不影响 stretch。
(注意:这里 Tk 应该大写,但也可能视环境略有不同。)
答案:D. opts = Tk.BOTH, Tk.FALSE
Question 27
What is the purpose of "setter" methods as they pertain to objects?
A. They are used to change the value of a private variable.
B. They are used to retrieve the value of a private variable.
C. They change a private variable to a public one and vice-versa.
D. They ensure that all private variables have the correct type.
E. None of the above
查看答案与解析
解析:
Setter(设置器)是专门用于修改对象私有属性的方法。
Getter(获取器)则是读取私有属性。
与修改属性的访问权限无关。
答案:A. They are used to change the value of a private variable.
Question 28
How many exclamation marks ! are in output.txt after running (only) the following code?
the_file = open("output.txt", 'a')
for k in range(1, 4):
the_file.write(k * '!')
the_file.close()
A. 1
B. 3
C. 6
D. Impossible to deduce without knowing the initial contents of output.txt.
E. None of the above
查看答案与解析
解析:
range(1,4) 是 [1,2,3]
写入的内容是:
1 * '!' = '!'
2 * '!' = '!!'
3 * '!' = '!!!'
总共写入 1 + 2 + 3 = 6 个感叹号。
注意'a'模式是追加,但不影响本题,因为是问新写入的量。
答案:C. 6
Question 29
Which of the following is not a necessary feature of an imperative programming language?
A. Iteration.
B. Selection.
C. Transparency.
D. Sequencing.
E. None of the above
查看答案与解析
解析:
迭代(Iteration)、选择(Selection)、顺序(Sequencing)是命令式编程语言的基本特征。
透明性(Transparency)不是编程语言必须具备的特征,它属于设计原则或系统属性。
答案:C. Transparency
Question 30
What is the value of z after running the following code?
xs = ['a', (3, 4), {1: 'b'}]
ys = xs.copy()
ys[2] = {2: 'c'}
z = xs[2][1]
A. 'a'
B. 'b'
C. 'c'
D. Error
E. None of the above
查看答案与解析
解析:
xs.copy()是浅拷贝,复制列表本身,但元素引用不变。
ys[2] = {2:'c'} 改变了 ys 的第 3 个元素,不影响原来的 xs。
所以 xs[2]仍然是{1: 'b'}。
xs[2][1]取 key=1,value 是'b'。
答案:B. 'b'
Question 31
What does a.f(4) return?
class A(object):
def __init__(self, x):
self._x = 2 * x
def f(self, x):
return self.g(x) + 2
def g(self, x):
return x - 1
class B(A):
def g(self, y):
return self._x + y
class C(B):
def __init__(self, x, y):
super().__init__(x)
self._y = y + 2
def f(self, x):
return self._x + self._y
class D(B):
def __init__(self, x, y):
super().__init__(x)
self._x += y
self._y = y + 2
def f(self, y):
return self._y + y
def g(self, x):
return super().g(x) - x
a = A(1)
b = B(2)
c = C(3, 4)
d = D(5, 6)
查看答案与解析
解析:
a = A(1),所以 self._x = 2
a.f(4)调用了 self.g(4) + 2
g(4)在 A 中定义,返回 4 - 1 = 3
所以 3 + 2 = 5
答案:5
Question 32
What does b.g(3) return?
查看答案与解析
解析:
b = B(2),self._x = 4
b.g(3)调用了子类 B 的 g 方法,返回 self._x + y
即 4 + 3 = 7
答案:7
Question 33
What does c.f(2) return?
查看答案与解析
解析:
c = C(3, 4)
self._x = 2 * 3 = 6
self._y = 4 + 2 = 6
c.f(2)返回 self._x + self._y,即 6 + 6 = 12
答案:12
Question 34
What does d.f(1) return?
查看答案与解析
解析:
d = D(5, 6)
self._x = 2 * 5 = 10,然后 self._x += 6 → self._x = 16
self._y = 6 + 2 = 8
d.f(1)调用 return self._y + y → 8 + 1 = 9
答案:9
Question 35
What does d.g(0) return?
查看答案与解析
解析:
d.g(0)调用了重写的 g 方法:super().g(x) - x
先调用 super().g(0),即 B.g(0),返回 self._x + y = 16 + 0 = 16
然后 16 - 0 = 16
答案:16
Question 36
Implement the following function according to its specification:
def foo(xs: str, ys: str) -> bool:
"""
Given two strings xs and ys, return true only when xs is equal
to ys when typed into an empty text editor interpreting '!' as
typing a backspace character.
For example:
>>> foo("ab!c", "ac")
True
because "ab!c" becomes "ac" when typed.
>>> foo("ab!!", "ab")
False
because "ab!!" becomes "" (empty string) when typed.
>>> foo("a!c", "c")
True
because "a!c" becomes "c" when typed.
Note that backspacing on the empty string produces the empty string.
"""
查看答案与解析
解析:
题目要求模拟输入过程,遇到!执行退格删除前一个字符。 常用方法是使用一个栈来模拟编辑器。
处理步骤:
遍历字符串
正常字符入栈
遇到'!',弹栈(如果栈非空)
最后将处理完的字符串与ys比较
示例参考实现:
def process(s: str) -> str:
stack = []
for c in s:
if c == '!':
if stack:
stack.pop()
else:
stack.append(c)
return ''.join(stack)
def foo(xs: str, ys: str) -> bool:
return process(xs) == ys
注意:
stack模拟输入框。
!不会让字符串长度变负数,如果没有字符,退格也是安全操作。
直接比较process(xs)和ys即可。
答案:
def foo(xs: str, ys: str) -> bool:
stack = []
for c in xs:
if c == '!':
if stack:
stack.pop()
else:
stack.append(c)
return ''.join(stack) == ys