for the full notebook with deeper explanations, see my TCX1002 Notebook.
Mistakes
map/sort/round/split
1map(fn, iter) # NO key=
2sorted(data, key=lambda x: ...) # HAS key=
3
4round(2.5) # 2 ← NOT 3! round(3.5) → 4 (banker's rounding)
5# need "always up"? → math.ceil()
6
7"".split(" ") # [""] ← NOT []!
8"".split() # [] ← 无参数 = 空 list
9
10sorted(lst) # returns NEW list
11lst.sort() # returns None, modifies in-place
Mutable Default
1def append_to(item, target=[]):
2 target.append(item)
3 return target
4
5a = append_to(1) # [1]
6b = append_to(2) # [1, 2] ← 不是 [2]!
7a is b # True ← 同一个 list!
8
9# ✅ FIX:
10def append_to(item, target=None):
11 if target is None:
12 target = []
13 target.append(item)
14 return target
= vs +=
1y = x # alias
2y = y + [6] # ✅ 新对象,x 不变
3y += [6] # ❌ in-place,x 也变!
4y.extend([6]) # ❌ in-place,x 也变!
[[x]] * n 共享引用
1[[0]] * 3 # [[0], [0], [0]] — 3个ref指向同一个[0]
2[[0] * 3] # [[0, 0, 0]] — 1个list包含3个0
3[0] * 3 # [0, 0, 0] — int是immutable,没问题
4
5# ❌ 共享引用
6a = [[0]] * 3
7a[0].append(1) # [[0,1], [0,1], [0,1]] ← 全变!
8
9# ✅ FIX: comprehension
10a = [[0] for _ in range(3)] # 3个独立list
11
12# 安全创建 1D / 2D / 3D
13a = [0] * 5 # 1D
14b = [[0] * 4 for _ in range(3)] # 2D (3×4)
15c = [[[0] * 4 for _ in range(3)] for _ in range(2)] # 3D (2×3×4)
Mutation During Iteration
1nums = [1, 2, 3, 4, 5]
2for n in nums:
3 if n % 2 == 0:
4 nums.remove(n)
5# for 底层用 index!remove 后 list 左移,下一个被跳过
6
7# ✅ FIX: comprehension
8nums = [n for n in nums if n % 2 != 0]
UnboundLocalError
1x = 10
2def bar():
3 x = foo(x) # Python 编译时看到 x=... → 整个函数 x 是 local
4 return x # foo(x) 读 local x,但还没赋值 → boom
5
6# ✅ FIX: 换变量名
7def bar():
8 y = foo(x) # x 没被赋值,读 global
9 return y
| Keyword | 用途 |
|---|
global x | 用模块级的 x |
nonlocal x | 用外层函数的 x(嵌套函数) |
Truthiness
1bool("") # False — 空 string
2bool("0") # True! — 非空 string(内容不管)
3bool([0]) # True! — 非空 list(内容不管)
4bool(0) # False — 零
5bool(None) # False
6
7# 规则:空容器/0/None/False = falsy,其他全 truthy
8# filter(None, iter) = 用 truthiness 过滤
9filter(None, [0, "", None, 1, "hello", [], False]) # → [1, "hello"]
Shallow Copy
1a = [[1,2], [3,4]]
2b = a[:] # shallow copy — 外层新,内层共享
3b[0].append(5)
4# a = [[1,2,5], [3,4]] ← a 也变了!
5
6# ✅ FIX: 手动 deep copy(copy 模块不能用)
7b = [row[:] for row in a]
extend vs append
1out.append([1,2]) # [..., [1,2]] ← 整个 list 当一个元素
2out.extend([1,2]) # [..., 1, 2] ← 逐个加入
Other
1[1,2] == [1,2] # True (content)
2[1,2] is [1,2] # False (identity)
3# is 只用于: x is None
4
5for i in range(5): pass
6print(i) # 4 — loop var 不会消失
Built-in Methods
1# STRING
2"hello world".split() # ['hello', 'world'] (按空白切)
3"a,b,c".split(",") # ['a', 'b', 'c'] (按指定切)
4" hello ".strip() # 'hello' (去两端空白)
5" hello ".lstrip() # 'hello ' (去左)
6" hello ".rstrip() # ' hello' (去右)
7"hello world".replace("world", "python") # 'hello python'
8", ".join(["a", "b", "c"]) # 'a, b, c' (list → str)
9"hello".upper() # 'HELLO'
10"HELLO".lower() # 'hello'
11"hello world".title() # 'Hello World'
12"hello".capitalize() # 'Hello' (只首字母)
13"hello".startswith("he") # True
14"file.py".endswith(".py") # True
15"abcabc".count("a") # 2
16"hello".find("ll") # 2 (index, 没找到返回 -1)
17
18# str.isXXX — 全部字符都要满足才 True, 空字符串返回 False
19"123".isdigit() # True
20"abc".isalpha() # True
21"abc123".isalnum() # True (字母或数字)
22"ABC".isupper() # True
23"abc".islower() # True
24
25# BUILTINS
26len(x) # 长度 (str, list, dict, set)
27abs(-5) # 5
28round(2.5) # 2 ← banker's rounding! (见 Mistakes)
29sorted(lst, reverse=True) # 降序 (返回新 list)
30min(lst, key=lambda x: x[1]) # 按第2元素找最小
31max(lst, key=lambda x: x[1]) # 按第2元素找最大
32any(x > 5 for x in lst) # 有一个满足就 True
33all(x > 0 for x in lst) # 全部满足才 True
34enumerate(lst) # → (0,a), (1,b), (2,c) — for i,v in ...
35list(filter(lambda x: x > 0, [-1, 0, 2, 3])) # [2, 3]
36ord('A') # 65 ord('Z') = 90
37ord('a') # 97 ord('z') = 122
38ord('0') # 48 ord('9') = 57
39chr(65) # 'A' chr(97) = 'a'
40# ord/chr hacks
41ord('c') - ord('a') # 2 — 字母→index (a=0, b=1, ...)
42chr(ord('a') + 3) # 'd' — index→字母
43chr(ord('A') + i) # 'A','B','C'... — 生成大写序列
44chr((ord(c) - ord('a') + shift) % 26 + ord('a')) # Caesar cipher shift
45
46# LIST
47lst.insert(1, "x") # 在 index 1 插入 (in-place)
48lst.pop() # 删最后一个并返回
49lst.pop(0) # 删 index 0 并返回
50lst.remove("x") # 删第一个 "x" (in-place, 没有则 ValueError)
51lst.reverse() # in-place, 返回 None! (同 .sort())
52lst.index("x") # 第一个 "x" 的 index (没有则 ValueError)
53
54# DICT
55d.get(key, default) # 没有 key 不报错,返回 default
56d.keys() # dict_keys([...])
57d.values() # dict_values([...])
58d.items() # dict_items([(k,v), ...]) ← for k,v in d.items()
59d.pop("key") # 删 key 并返回 value (没有则 KeyError!)
60d.pop("key", None) # 安全版,没有返回 None
61d.update({"a": 1, "b": 2}) # 批量更新/合并
62
63# dict counting (替代 defaultdict(int))
64counts = {}
65counts[item] = counts.get(item, 0) + 1
66
67# dict grouping (替代 defaultdict(list))
68groups = {}
69groups.setdefault(key, []).append(item)
70
71# dict grouping with set (替代 defaultdict(set))
72groups.setdefault(key, set()).add(item)
73
74# SET
75s.add(x) # 加一个元素
76s.discard(x) # 删元素 (没有也不报错)
77s.remove(x) # 删元素 (没有则 KeyError!)
78a & b # intersection (交集)
79a | b # union (并集)
80a - b # difference (a有b没有)
81a ^ b # symmetric diff (只在一边有)
82
83# COMPREHENSION
84[x**2 for x in lst] # list comp
85[x for x in lst if x > 0] # 带条件
86{k: v for k, v in pairs} # dict comp
87{x for x in lst} # set comp
88[[row[i] for row in matrix] for i in range(n)] # nested (转置)
89
90# TYPE CHECK (A1Q2 用过)
91type(x) == str # True if str
92isinstance(x, (int, float)) # True if int or float (推荐)
Iterators(一次性)
1a = map(lambda x: x**2, [1,2,3])
2list(a) # [1, 4, 9]
3list(a) # [] ← 空了!
4
5# 一次性: map, filter, zip, enumerate, 所有 itertools
6# 可重复: range, list, tuple, set, dict
7
8# ✅ 安全做法:马上 list() 包住
9result = list(map(lambda x: x**2, data))
1from functools import reduce, partial
2from itertools import combinations, permutations, chain, product, accumulate
3
4# reduce — 一个最终值
5reduce(lambda acc, x: acc + x, [1,2,3,4]) # 10
6reduce(lambda acc, x: acc * x, [1,2,3,4]) # 24
7reduce(lambda acc, x: acc + x, [1,2,3], 100) # 106 (init=100)
8
9# partial — pre-fill args
10add10 = partial(lambda x, y: x + y, 10)
11add10(5) # 15
12
13combinations([1,2,3], 2) # [(1,2),(1,3),(2,3)] C(n,k)
14permutations([1,2,3], 2) # [(1,2),(1,3),(2,1),...] P(n,k)
15chain([1,2], [3,4]) # [1,2,3,4] flatten
16product([1,2], ['a','b']) # [(1,'a'),(1,'b'),(2,'a'),(2,'b')]
17accumulate([1,2,3,4]) # [1,3,6,10] 前缀和
18accumulate([3,1,4,1,5], max) # [3,3,4,4,5] running max
| 返回 |
|---|
reduce | 一个值 (折叠) |
accumulate | 所有中间值 (前缀) |
math
1import math
2
3math.ceil(2.1) # 3 (always round up)
4math.floor(2.9) # 2 (always round down)
5math.sqrt(16) # 4.0 (or x ** 0.5)
6math.log(8, 2) # 3.0 (log base 2)
7math.log(math.e) # 1.0 (natural log)
8math.factorial(5) # 120
9math.gcd(12, 8) # 4
10math.pi # 3.14159...
11math.e # 2.71828...
12math.inf # infinity (or float('inf'))
datetime
1from datetime import datetime, date, timedelta
2
3# 创建
4today = date.today() # date(2026, 2, 14)
5now = datetime.now() # datetime(2026, 2, 14, 10, 30, 0)
6d = date(2026, 2, 14) # 指定日期
7dt = datetime(2026, 2, 14, 10, 30) # 指定日期+时间
8
9# 属性
10d.year, d.month, d.day # 2026, 2, 14
11dt.hour, dt.minute, dt.second # 10, 30, 0
12
13# timedelta — 加减时间
14d + timedelta(days=7) # 7天后
15d - timedelta(weeks=2) # 2周前
16dt + timedelta(hours=2, minutes=30) # 可以混用 (⚠️ 要 datetime 不是 date!)
17(date(2026, 3, 1) - date(2026, 2, 14)).days # 15(差几天)
18
19# 格式化
20dt.strftime("%Y-%m-%d %H:%M") # '2026-02-14 10:30'
21datetime.strptime("14/02/2026", "%d/%m/%Y") # str → datetime
22# %Y=年4位 %m=月2位 %d=日2位 %H=时24 %M=分 %S=秒
23
24# 比较 (A1Q2 attendance)
25start = datetime(2025, 1, 1, 19, 0, 0)
26scanned = datetime(2025, 1, 1, 19, 8, 0)
27scanned <= (start + timedelta(minutes=15)) # True → on time
28end = datetime(2025, 1, 1, 21, 0, 0)
29(end - start) / 2 # 半场时间 (timedelta)
random
1import random
2
3random.randint(1, 10) # 1到10 的随机整数(包含两端)
4random.random() # 0.0 到 1.0 的随机浮点数
5random.uniform(1.5, 5.5) # 指定范围的随机浮点数
6random.choice([1, 2, 3]) # 随机选一个
7random.sample([1,2,3,4,5], 3) # 随机选3个(不重复,返回 list)
8random.shuffle(lst) # in-place 打乱(返回 None!)
9
10# 可重现
11random.seed(42) # 设 seed → 每次结果一样
NumPy
List vs NumPy:
| 操作 | List | NumPy |
|---|
a + b | 拼接 [1,2,3,4] | 逐元素加 [5,7,9] |
a * 3 | repeat [1,2,1,2,1,2] | 逐元素乘 [3,6,9] |
a > 1 | TypeError | bool array [F,T,T] |
len(a) | 元素个数 | 第一维长度 |
sum(a) | 总和 | 总和(但用 np.sum 更快) |
1# 同一个任务,List vs NumPy 写法对比:
2
3# 每个元素 +10
4[x + 10 for x in lst] # List: comprehension
5arr + 10 # NumPy: broadcasting
6
7# 过滤 >5
8[x for x in lst if x > 5] # List: comprehension
9arr[arr > 5] # NumPy: boolean indexing
10
11# 逐元素相乘
12[a*b for a,b in zip(l1, l2)] # List: zip + comprehension
13arr1 * arr2 # NumPy: 直接乘
14
15# 互转
16np.array([1,2,3]) # list → numpy
17arr.tolist() # numpy → list
1import numpy as np
2
3# 创建
4np.array([1,2,3]) # from list
5np.zeros((3,4)) # 3×4 全0
6np.ones((2,3)) # 2×3 全1
7np.arange(0, 10, 2) # [0, 2, 4, 6, 8]
8np.linspace(0, 1, 5) # [0, 0.25, 0.5, 0.75, 1.0]
9
10# shape 操作
11a.shape # (3, 4)
12a.reshape(2, 6) # 改形状(元素总数不变)
13a.flatten() # 拉成 1D
14a.T # 转置
15
16# axis — 0=行方向(↓列压缩), 1=列方向(→行压缩)
17np.sum(a, axis=0) # 每列的和
18np.sum(a, axis=1) # 每行的和
19np.mean(a, axis=0) # 每列平均
20np.max(a, axis=1) # 每行最大
21
22# boolean filter
23a[a > 5]
24
25# broadcasting (pairwise) — newaxis 插入维度
26R = a[:, np.newaxis, :] # (n, 1, d) — 中间插 = Row
27C = a[np.newaxis, :, :] # (1, n, d) — 前面插 = Column
28D = R - C # (n, n, d) — 所有 pair 的差
29# 规则: 从右对齐,1可以拉伸 → (1,3) + (2,1) → (2,3)
30
31# useful ops
32np.where(a > 5) # 满足条件的 index 数组
33np.argmax(a) # 最大值的 index
34np.argsort(a) # 排序后的 index 数组
35np.dot(a, b.T) # 矩阵点积
36np.linalg.norm(a, axis=1) # 每行的向量长度 (L2 norm)
37np.outer(a, b) # 外积 (n,) × (m,) → (n,m)
38
39# local peaks (T1Q4)
40lefts, currs, rights = x[:-2], x[1:-1], x[2:]
41scale = 1 + threshold
42peaks = np.where((currs > lefts*scale) & (currs > rights*scale))[0] + 1
43
44# pairwise distances (T3Q4)
45manhattan = np.sum(np.abs(D), axis=2)
46euclidean = np.sqrt(np.sum(np.square(D), axis=2))
47
48# cosine distance (T3Q4)
49dot_products = np.dot(a, a.T)
50norms = np.linalg.norm(a, axis=1)
51cosine = 1 - dot_products / np.outer(norms, norms)
Regex
| 函数 | 从哪找 | 返回 | 没找到 |
|---|
re.findall(pat, text) | 所有匹配 | list of strings | [] |
re.match(pat, text) | 开头 | match object | None |
re.search(pat, text) | 任意位置(第一个) | match object | None |
re.sub(pat, repl, text) | 全部替换 | new string | 原 string |
re.split(pat, text) | 按 pattern 切 | list of strings | [原text] |
re.fullmatch(pat, text) | 整个 string | match object | None |
1# findall — 返回 strings!不是 int
2re.findall(r'\d+', "age 25, score 99") # ['25', '99']
3nums = list(map(int, re.findall(r'\d+', s))) # 转 int
4
5# search — 返回 match object
6m = re.search(r'(\d+)-(\d+)', "call 123-456 now")
7m.group(0) # '123-456' ← 完整匹配
8m.group(1) # '123' ← 第一个 ()
9m.group(2) # '456' ← 第二个 ()
10
11# ⚠️ match/search 可能返回 None,先检查!
12m = re.search(r'\d+', text)
13if m is not None:
14 print(m.group())
15
16# sub — 替换
17re.sub(r'\d+', 'X', "abc123def456") # 'abcXdefX'
18re.sub(r'\s+', ' ', " too many ").strip() # 'too many'
19
20# split — 按多种分隔符
21re.split(r'[,;\s]+', "a, b;c d") # ['a', 'b', 'c', 'd']
22
23# greedy vs non-greedy
24re.findall(r'<.+>', '<a><b>') # ['<a><b>'] ← greedy(尽量多)
25re.findall(r'<.+?>', '<a><b>') # ['<a>', '<b>'] ← non-greedy(尽量少)
26
27# findall + groups — 有 () 时只返回 group 内容
28re.findall(r'(\d+)-(\d+)', "12-34 56-78") # [('12','34'), ('56','78')]
29
30# fullmatch — 整个 string 必须匹配
31re.fullmatch(r'[A-Z]{3}\d{4}', "ABC1234") # match
32re.fullmatch(r'[A-Z]{3}\d{4}', "ABC12345") # None
常用例子
1re.findall(r'\d{2}/\d{2}/\d{4}', "born 14/02/2026") # 提取日期
2re.findall(r'\(([^)]+)\)', "f(x) and g(y)") # 括号内容 → ['x','y']
3re.findall(r'(\w+)=(\w+)', "name=bob age=25") # key=value pairs
T3Q1 车牌技巧
1r'[A-HJ-NP-Z]' # A-Z 排除 I 和 O — 多段 range
2r'(?=([A-HJ-NP-Z]{2,3}\d{1,4}[A-Z]))' # lookahead 找重叠匹配
3m = re.match(r'^([A-Z]+)', "SGP1234A") # match 提取 prefix
4r'\d{1,4}' # {n,m} 精确量词
Regex Notes
1# 为什么用 r'' (raw string)?
2r'\d+' # ✅ backslash 原样传给 regex
3'\d+' # ⚠️ Python 先处理 \d → 可能出错
4# 规则:regex pattern 永远用 r''
5
6# \d vs \d+ — Q25 踩过
7re.findall(r'\d', "abc123") # ['1', '2', '3'] ← 每个数字
8re.findall(r'\d+', "abc123") # ['123'] ← 整个数字串
9
10# flags
11re.findall(r'hello', "Hello World", re.IGNORECASE) # ['Hello']
12re.search(r'hello', "Hello", re.I) # match (re.I = 缩写)
Pattern 速查
| Pattern | Meaning | Example |
|---|
. | any char (except \n) | a.c → abc, a1c |
\d / \D | digit / non-digit | \d = [0-9] |
\w / \W | word char / non-word | \w = [a-zA-Z0-9_] (含下划线!) |
\s / \S | whitespace / non-ws | space, tab, newline |
\b | word boundary | r'\bcat\b' 只匹配整个 “cat”,不匹配 “catch” |
[A-Z] | char range | [a-zA-Z] = 所有字母 |
[^A-Z] | NOT (negated class) | [^0-9] = 非数字 |
+ / * / ? | 1+ / 0+ / 0 or 1 | \d+ = 一个或多个数字 |
{n} / {n,m} | exactly n / n to m | \d{4} = 4位数字 |
^ / $ | start / end of string | ^Hello = 开头是 Hello |
(...) | capture group | findall 只返回 group 内容 |
(?:...) | non-capture group | 分组但不 capture |
(?=...) / (?!...) | lookahead / neg | 看前面但不消耗 |
(?<=...) / (?<!...) | lookbehind / neg | 看后面但不消耗 |
Good to Know
1x ** 0.5 # sqrt (no import)
2float('inf') # infinity (no import)
3frozenset({1,2}) # immutable set, can be dict key
4t = ("A", 1, 2, 3)
5t[1:] # (1, 2, 3) — tuple slicing works like list
6
7# 常用 1-liners
8list(dict.fromkeys([1,3,2,1,3])) # [1,3,2] — 去重保序
9[x for row in [[1,2],[3,4]] for x in row] # [1,2,3,4] — 展平 2D
10list(zip(*[[1,2],[3,4]])) # [(1,3),(2,4)] — 转置
11sorted([("A",2),("B",1),("C",2)], key=lambda x: (-x[1], x[0])) # [("A",2),("C",2),("B",1)]
12a, *rest = [1,2,3,4] # a=1, rest=[2,3,4]
13[1,2,3][::-1] # [3,2,1] — 反转 (不改原 list)
Pre-Submit Checklist
1EDGE CASES
2□ Empty: [], "", {}, 0, None
3□ Single: [1], "a"
4□ All same: [5,5,5,5]
5□ Negative/zero: [-1, 0, 1]
6□ Boundaries: first, last, exactly at condition
7□ Duplicates: [1,1,2,2] — does spec say unique?
8□ Sorted/reverse: [1,2,3], [3,2,1]
9
10CORRECTNESS
11□ Re-read spec: am I solving what was ACTUALLY asked?
12□ Return type: list? tuple? string? int? float? match spec
13□ Return value: return X, not print(X)
14□ Off-by-one: range(n) vs range(n+1), < vs <=, [L:R] vs [L:R+1]
15□ Mutation: did I modify the original input? (spec may need it intact)
16□ Case: .lower() if spec says case-insensitive
17
18CLEANUP
19□ Remove print(): all debug prints gone
20□ Shadowing: didn't name vars list, dict, sum, max, min, type, id
21□ Imports: all needed modules imported at top
22□ Fn signature: matches spec exactly (name, params, defaults)