Files
2026-10-07 23:41:29 +08:00

107 lines
4.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
一、选择题
1. B 2. B 3. B 4. B 5. B 6. B 7. B 8. B 9. B 10. B
每题思路
1. `[1, 2]` —— 可变默认参数:`def f(x, lst=[])` 里的 `[]` 只在函数定义时创建一次,之后所有调用共用同一个列表。`f(1)` 后是 `[1]`,`f(2)` 再 append 2 变成 `[1, 2]`。
2. `[1, 2, 3, 4] [1, 2, 3]` —— `b = a` 是别名(指向同一列表),`c = a.copy()` 是复制出的新列表。`a.append(4)` 改的是 a/b 共用的列表,所以 b 变、c 不变。
3. 输出 A 和 C —— 出错走 `except` 打印 A;`else` 只在没出错时执行(这里出错,跳过);`finally` 一定执行打印 C。
4. `7 5` —— `" hello "` 是 1 空格 + 5 字母 + 1 空格 = 7 个字符;`strip()` 去掉首尾空格后 `"hello"` 长 5。
5. 只输出 end —— for 循环被 `break` 打断时,`else` 不执行,所以 `done` 不打印,只执行循环外的 `end`。
6. `Rex: woof` —— Dog 继承了 Animal 的 `__init__`,又重写了 `speak()`,所以 `d.speak()` 调用 Dog 版本,打印 `Rex: woof`。
7. `{'b': 2}` —— 字典推导式 `{k: v for k, v in d.items() if v > 1}` 只保留 `v > 1` 的项,只有 `"b": 2` 满足。
8. `<class 'str'>` —— `json.dumps()` 把字典序列化成 JSON 字符串,所以结果是 str。
9. 只输出 6 —— `f(5)` 单独一行返回了 6 但没打印,无输出;`print(f(5))` 才打印 6,所以只有一行 6。
10. get() 返回 None,[] 抛 KeyError —— `user.get("city")` 键不存在返回 None(不报错),`user["city"]` 键不存在抛 KeyError。
二、简答题
第 1 题:浅拷贝与深拷贝
```python
a = [[1, 2], [3, 4]]
b = a.copy()
import copy
c = copy.deepcopy(a)
```
三者关系:
- `a`:原列表 `[[1, 2], [3, 4]]`
- `b = a.copy()`:浅拷贝,外层列表是新的,但内层列表还是和 a 共享的同一个对象(`b[0] is a[0]` 为 True)
- `c = copy.deepcopy(a)`:深拷贝,外层、内层全是独立的新对象(`c[0] is a[0]` 为 False)
执行 `a[0].append(99)` 后:
- `b` → `[[1, 2, 99], [3, 4]]`(因为 b[0] 和 a[0] 是同一个内层列表,一起变了)
- `c` → `[[1, 2], [3, 4]]`(c 的内层是独立副本,不受影响)
原因:浅拷贝只复制最外层容器,内部元素仍是引用(指向同一对象);深拷贝会递归复制每一层,得到完全独立的对象。
第 2 题:字典与列表的综合应用
```python
logs = [
{"user": "张三", "action": "login", "level": "INFO"},
{"user": "李四", "action": "logout", "level": "INFO"},
{"user": "张三", "action": "error", "level": "ERROR"},
{"user": "王五", "action": "login", "level": "INFO"},
{"user": "李四", "action": "error", "level": "ERROR"},
]
```
找出所有 level 为 "ERROR" 的日志:
```python
error_logs = [log for log in logs if log["level"] == "ERROR"]
# [{'user': '张三', 'action': 'error', 'level': 'ERROR'},
# {'user': '李四', 'action': 'error', 'level': 'ERROR'}]
```
统计每个用户出现几次:
```python
user_count = {}
for log in logs:
user = log["user"]
user_count[user] = user_count.get(user, 0) + 1
# {'张三': 2, '李四': 2, '王五': 1}
```
也可以用 `collections.Counter` 一行完成:`Counter(log["user"] for log in logs)`。
为什么不能用 len(logs):`len(logs)` 只返回日志的总条数(这里是 5),它不做任何分类统计。要按用户分别计数,必须用一个 for 循环逐条遍历 logs,取出每条里的 `"user"` 字段,再用字典以用户名为键累加次数。所以需要的是「for 遍历 + 字典累加」这种结构,而不是一个 `len()`。
第 3 题:异常处理设计
函数代码:
```python
def safe_divide(a, b):
try:
return float(a) / float(b)
except (ValueError, ZeroDivisionError):
return None
```
说明:
- `float(a)`、`float(b)` 把字符串转成数字,转不了会抛 ValueError;
- b 是 "0" 时 `float(b)` 为 0.0,做除法抛 ZeroDivisionError;
- 两种异常在同一个 except 里捕获,统一返回 None。
为什么用 try/except 比先用 if 判断更好:
- 避免重复转换:用 if 先判断"能不能转",得先试转一次确认、再转一次真正计算,等于转两遍;try/except 直接转,失败就捕获。
- 一个 try 块覆盖多个出错点:a 转失败、b 转失败、除数为零,if 要写一串嵌套判断,try 一个块全包住。
- 更符合 Python 的 EAFP 风格(先做、出错再补救),比 LBYL(先判断再执行)更简洁健壮。