pandas 代码 = Python 内功 + 表格思维。第 3 章补齐内功:四大容器、函数的进阶玩法、文件读写。这一章的每个知识点都会在后面几十处反复出现,值得慢读。
📦 四大容器:tuple / list / dict / set
元组 tuple:一寸不可变
t = 1, 2, 3 # 括号可省
nested = (1, (2, 3), [4, 5]) # 可嵌套
a, b, c = t # 解包:一行拆出所有值
first, *rest = [1, 2, 3, 4] # 星号吃掉剩余:rest = [2, 3, 4]
t.count(2) # 统计出现次数
不可变是它的性格:不能增删改。但注意「不可变的是引用」——元组里的列表照样能 append。函数返回多个值(本质是返回一个元组)和变量交换 a, b = b, a 全靠解包这一手。
列表 list:万能收纳箱
lst = ["a", "b", "c"]
lst.append("d") # 尾部加
lst.insert(1, "x") # 指定位置插(慎用,O(n))
lst.pop(2) # 弹出并返回
lst.remove("x") # 按值删第一个
"b" in lst # True,成员判断
lst2 = [7, 2, 5, 1, 3]
lst2.sort() # 原地排序
lst2.sort(key=len) # 或按函数返回值排序
切片是列表(也是 NumPy/pandas)的灵魂操作:
seq = [7, 2, 3, 7, 5, 6, 0, 1]
seq[1:5] # [2, 3, 7, 5],左闭右开
seq[::2] # [7, 3, 5, 0],隔一个取
seq[::-1] # 反转
seq[1:5] = [8, 8, 8, 8] # 切片赋值
⚠️ 切片是副本(列表上),和 NumPy 的视图规则不同,别混淆。
字典 dict:O(1) 的键值魔法
d1 = {"a": 1, "b": [1, 2, 3]}
d1["c"] = 5 # 新增/覆盖
d1.get("x", 0) # 安全取值,不存在返回默认 0
d1.keys() / d1.values() / d1.items()
# 合并(Python 3.5+ 神语法)
d2 = {"b": 99, "d": 4}
{**d1, **d2}
两个经典套路:按值分组建多值字典,以及 zip 交替两列表成对:
from collections import defaultdict
groups = defaultdict(list)
for w in ["apple", "ant", "banana", "bat"]:
groups[w[0]].append(w) # {'a': ['apple','ant'], 'b': [...]}
letters = list("abcd"); nums = range(4)
dict(zip(letters, nums)) # {'a':0,'b':1,'c':2,'d':3}
集合 set:去重 + 数学运算
a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7}
a & b # 交集 {3,4,5}
a | b # 并集
a - b # 差集
a ^ b # 对称差(只在一方出现)
set(list) 一行去重,比循环快得多。
🧰 内置序列函数与推导式
enumerate(带下标遍历)、sorted(返回新列表)、zip(平行遍历)、reversed(反向迭代)——四个瑞士军刀。
推导式是 Python 优雅的巅峰,允许条件与嵌套:
strings = ["a", "as", "bat", "car", "dove", "python"]
[x.upper() for x in strings if len(x) > 2]
# ['BAT', 'CAR', 'DOVE', 'PYTHON']
{val: i for i, val in enumerate(strings)} # 字典推导式
lengths = {x: len(x) for x in strings}
unique = {len(x) for x in strings} # 集合推导式 {1,2,3,4,6}
all_data = [["John", "Emily"], ["Mike", "Mary"]]
names = [n for names in all_data for n in names if n.count("m") > 0]
pandas 源码和数据分析脚本里推导式无处不在,读懂它 = 读懂一半 Python 代码。
🧩 函数的进阶心法
函数皆对象——可以赋值、传参、存进字典:
def clean_str(s): return s.strip().title()
ops = {"clean": clean_str, "upper": str.upper}
ops["clean"](" hello world ") # 'Hello World'
lambda:匿名小函数,pandas 里天天见:
df.apply(lambda x: x.max() - x.min()) # 每列极差
生成器:yield 逐个吐值,不占整块内存——处理大文件/大序列的利器:
def squares(n):
for i in range(n):
yield i ** 2
gen = squares(10)
sum(gen) # 285,惰性求值
sum(x ** 2 for x in range(10)) # 生成器表达式:小括号版推导式
异常处理:数据分析脚本要敢于捕获、优雅降级:
try:
float("abc")
except (TypeError, ValueError) as e:
print(f"转不动:{e}")
finally:
print("无论如何都执行(常用于关资源)")
📂 文件与操作系统
path = "data.txt"
with open(path, encoding="utf-8") as f:
lines = [line.rstrip() for line in f] # with 块结束自动关闭
⚠️ 两个坑:一,永远用 with 打开文件,忘记 close 的文件句柄会泄漏;二,永远显式写 encoding="utf-8"——Windows 默认 GBK,中文文件一不留神就乱码。二进制文件用 "rb" 模式,得到的是 bytes 对象。
📌 本章小结:tuple 不可变可解包、list 是切片主场、dict 是 O(1) 查找、set 管去重和集合运算;推导式要写到手熟;函数是对象、lambda 是 pandas 常客、yield 省内存;文件永远
with open(..., encoding="utf-8")。内功齐了,下一章正式进入 NumPy。