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

4.5 KiB
Raw Permalink Blame History

一、选择题

  1. B 2. B 3. B 4. B 5. B 6. B 7. B 8. B 9. B 10. B 每题思路

  2. [1, 2] —— 可变默认参数:def f(x, lst=[]) 里的 [] 只在函数定义时创建一次,之后所有调用共用同一个列表。f(1) 后是 [1],f(2) 再 append 2 变成 [1, 2]。

  3. [1, 2, 3, 4] [1, 2, 3] —— b = a 是别名(指向同一列表),c = a.copy() 是复制出的新列表。a.append(4) 改的是 a/b 共用的列表,所以 b 变、c 不变。

  4. 输出 A 和 C —— 出错走 except 打印 A;else 只在没出错时执行(这里出错,跳过);finally 一定执行打印 C。

  5. 7 5 —— " hello " 是 1 空格 + 5 字母 + 1 空格 = 7 个字符;strip() 去掉首尾空格后 "hello" 长 5。

  6. 只输出 end —— for 循环被 break 打断时,else 不执行,所以 done 不打印,只执行循环外的 end。

  7. Rex: woof —— Dog 继承了 Animal 的 __init__,又重写了 speak(),所以 d.speak() 调用 Dog 版本,打印 Rex: woof。

  8. {'b': 2} —— 字典推导式 {k: v for k, v in d.items() if v > 1} 只保留 v > 1 的项,只有 "b": 2 满足。

  9. <class 'str'> —— json.dumps() 把字典序列化成 JSON 字符串,所以结果是 str。

  10. 只输出 6 —— f(5) 单独一行返回了 6 但没打印,无输出;print(f(5)) 才打印 6,所以只有一行 6。

  11. get() 返回 None,[] 抛 KeyError —— user.get("city") 键不存在返回 None(不报错),user["city"] 键不存在抛 KeyError。

二、简答题

第 1 题:浅拷贝与深拷贝

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 题:字典与列表的综合应用

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" 的日志:

error_logs = [log for log in logs if log["level"] == "ERROR"]
# [{'user': '张三', 'action': 'error', 'level': 'ERROR'},
#  {'user': '李四', 'action': 'error', 'level': 'ERROR'}]

统计每个用户出现几次:

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 题:异常处理设计

函数代码:

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(先判断再执行)更简洁健壮。