Python 进阶必备:JSON与Pickle数据持久化、Turtle绘图实战 与 函数编程 5 大模块,一篇搞定!
摘要
还在为 Python 数据如何保存到文件而头疼?好奇那些炫酷的 Turtle 图形是怎么画出来的?函数参数 *args 和 **kwargs 总是傻傻分不清?本文一次性覆盖 JSON 与 Pickle 数据持久化、Turtle 图形绘制实战、函数基础、五大参数类型、Lambda 匿名函数五大核心模块,每个知识点都配有可独立运行的代码示例和速查表格,适合正在进阶的 Python 学习者收藏备用。
一文掌握 Python 数据序列化、图形绘制与函数编程五大核心模块,从基础到实战,代码即复制即用!
在 Python 学习的路上,有几个坎是绕不开的:如何把内存中的数据存到硬盘?如何用代码画出直观的图形?函数参数为什么有时加 * 有时加 **?本文把这些知识点串联起来,用「数据持久化 → 图形可视化 → 函数抽象」的递进逻辑,帮你建立完整的知识体系。
一、数据持久化:JSON 与 Pickle
程序运行时的数据存在内存里,一旦程序结束就没了。想要把数据「留下来」,就要用到序列化——把 Python 对象转成可以存到文件或通过网络传输的格式。
Python 内置了两个最常用的序列化模块:JSON(跨语言通用)和 Pickle(Python 专用)。
1.1 JSON 序列化与反序列化
JSON(JavaScript Object Notation)是业界通用的数据交换格式,几乎所有编程语言都支持。
四个核心函数:
| json.dumps(obj) | Python → JSON 字符串 | 序列化为字符串(内存中) |
| json.dump(obj, f) | Python → JSON 文件 | 序列化并写入文件 |
| json.loads(s) | JSON 字符串 → Python | 从字符串反序列化 |
| json.load(f) | JSON 文件 → Python | 从文件读取并反序列化 |
import json
# === dumps / loads:字符串级别的序列化 ===
data = {"name": "张三", "age": 25, "skills": ["Python", "Java"]}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)
# {
# "name": "张三",
# "age": 25,
# "skills": ["Python", "Java"]
# }
# 从 JSON 字符串还原为 Python 对象
restored = json.loads(json_str)
print(restored) # {'name': '张三', 'age': 25, 'skills': ['Python', 'Java']}
print(type(restored)) # <class 'dict'>
import json
import os
# === dump / load:文件级别的序列化 ===
data = {"name": "张三", "age": 25, "skills": ["Python", "Java"]}
# 写入 JSON 文件
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 从 JSON 文件读取
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded) # {'name': '张三', 'age': 25, 'skills': ['Python', 'Java']}
两个常用参数的说明:
- ensure_ascii=False:中文不会被转成 \\uXXXX,可读性大幅提升
- indent=2:格式化输出,每层缩进 2 个空格
JSON 类型映射表:
| dict | object |
| list / tuple | array |
| str | string |
| int / float | number |
| True / False | true / false |
| None | null |
注意: JSON 不能直接序列化 Python 特有的类型,比如 datetime、set、自定义类等。这时需要自定义编码器。
import json
from datetime import datetime
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.strftime("%Y-%m-%d %H:%M:%S")
return super().default(obj)
data = {"time": datetime.now(), "user": "张三"}
json_str = json.dumps(data, cls=CustomEncoder, ensure_ascii=False)
print(json_str) # {"time": "2026-07-22 10:30:00", "user": "张三"}
1.2 Pickle 序列化与反序列化
Pickle 是 Python 独有的序列化模块,能将几乎任意 Python 对象(包括函数、类、复杂嵌套结构)转换为字节流。
| pickle.dumps(obj) | Python → bytes | 内存中序列化 |
| pickle.dump(obj, f) | Python → 文件 | 写入二进制文件 |
| pickle.loads(data) | bytes → Python | 内存中反序列化 |
| pickle.load(f) | bytes 文件 → Python | 从二进制文件读取 |
import pickle
# === dumps / loads ===
data = {"name": "李四", "scores": [88, 92, 79], "passed": True}
binary = pickle.dumps(data)
print(binary) # b'\\x80\\x04\\x95…' (二进制字节流)
restored = pickle.loads(binary)
print(restored) # {'name': '李四', 'scores': [88, 92, 79], 'passed': True}
import pickle
# === dump / load:读写二进制文件 ===
data = {"name": "李四", "scores": [88, 92, 79]}
# 写入(注意是 "wb",二进制写模式)
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
# 读取(注意是 "rb",二进制读模式)
with open("data.pkl", "rb") as f:
loaded = pickle.load(f)
print(loaded) # {'name': '李四', 'scores': [88, 92, 79]}
1.3 JSON vs Pickle 对比
| 跨语言 | 是(所有语言通用) | 否(仅 Python) |
| 数据格式 | 文本(可读) | 二进制(不可读) |
| 支持类型 | 基础类型(dict/list/str/int 等) | 几乎任意 Python 对象 |
| 安全性 | 安全 | 不安全(不要 unpickle 不可信来源) |
| 适用场景 | API 数据交换、配置文件 | Python 内部数据缓存、模型保存 |
# 选择建议:
# – 需要跟其他语言/系统交互 → 选 JSON
# – 仅在 Python 内临时保存复杂对象 → 选 Pickle
# – 对外暴露的 API 或用户上传的数据 → 绝对不要用 Pickle
二、Turtle 图形绘制实战
Turtle(海龟作图)是 Python 自带的绘图库,通过控制"小海龟"在画布上移动来绘制图形。它直观、有趣,非常适合理解程序逻辑和坐标系统。
2.1 Turtle 快速入门
import turtle
# 基本设置
turtle.speed(5) # 速度:1(最慢) ~ 10(最快)
turtle.pensize(2) # 笔的粗细
turtle.pencolor("blue") # 笔的颜色
# 基础移动指令
turtle.forward(100) # 前进 100 像素
turtle.right(90) # 右转 90 度
turtle.forward(100) # 前进 100 像素
turtle.left(90) # 左转 90 度
turtle.backward(50) # 后退 50 像素
turtle.done() # 保持窗口不关闭
Turtle 常用指令速查:
| forward(d) / fd(d) | 前进 d 像素 |
| backward(d) / bk(d) | 后退 d 像素 |
| right(a) / rt(a) | 右转 a 度 |
| left(a) / lt(a) | 左转 a 度 |
| penup() / pu() | 抬笔(移动不画线) |
| pendown() / pd() | 落笔(开始画线) |
| goto(x, y) | 移动到指定坐标 |
| circle(r, extent) | 画圆/弧,r=半径,extent=角度 |
2.2 案例一:五角星
import turtle
turtle.speed(5)
turtle.pensize(2)
turtle.pencolor("red")
turtle.fillcolor("yellow")
turtle.begin_fill() # 开始填充
for _ in range(5):
turtle.forward(200) # 每条边长 200
turtle.right(144) # 五角星转 144 度
turtle.end_fill() # 结束填充
turtle.hideturtle() # 隐藏海龟
turtle.done()
五角星的核心在于转角:180 – 36 = 144 度。星形每个内角 36 度,海龟需要在顶点转 144 度。
2.3 案例二:彩色螺旋线
import turtle
turtle.speed(0) # 最快速度
colors = ["red", "orange", "yellow", "green", "blue", "purple"]
for i in range(100):
turtle.pencolor(colors[i % len(colors)]) # 循环取色
turtle.forward(i * 2) # 越走越长,形成螺旋
turtle.right(59) # 59 度转角产生螺旋效果
turtle.hideturtle()
turtle.done()
2.4 案例三:递归分形树
import turtle
def draw_tree(branch_len, t):
"""递归画分形树"""
if branch_len < 5: # 递归出口:树枝太短就不画了
return
t.forward(branch_len)
t.right(20) # 右分支
draw_tree(branch_len – 15, t) # 递归画右侧子树
t.left(40) # 左分支(相对于当前方向左转 40 度)
draw_tree(branch_len – 15, t) # 递归画左侧子树
t.right(20) # 回到原方向
t.backward(branch_len) # 退回起点
# 初始化
t = turtle.Turtle()
t.left(90) # 朝上
t.speed(0)
t.pensize(2)
t.pencolor("brown")
draw_tree(80, t)
turtle.hideturtle()
turtle.done()
分形树展现了递归的优雅:画一根主干 → 画右子树 → 画左子树 → 退回。每次递归树枝缩短,直到长度小于 5 停止。
三、函数基础
函数是代码复用的基本单元。把一段逻辑封装成函数,写好一次,到处调用。
3.1 函数定义与调用
# 定义函数
def greet(name):
"""向指定用户打招呼(这是文档字符串)"""
return f"你好,{name}!欢迎学习 Python。"
# 调用函数
result = greet("小明")
print(result) # 你好,小明!欢迎学习 Python。
# 查看文档字符串
print(greet.__doc__) # 向指定用户打招呼(这是文档字符串)
3.2 返回值的三种情况
# 1. 返回单个值
def add(a, b):
return a + b
# 2. 返回多个值(实际上返回的是元组)
def calculate(a, b):
return a + b, a – b, a * b
result = calculate(10, 3)
print(result) # (13, 7, 30)
print(type(result)) # <class 'tuple'>
# 可以用解包接收
sum_val, diff, prod = calculate(10, 3)
print(sum_val, diff, prod) # 13 7 30
# 3. 没有 return 语句 → 默认返回 None
def say_hello():
print("Hello")
result = say_hello() # 打印: Hello
print(result) # None
3.3 作用域:全局变量与局部变量
total = 100 # 全局变量
def calculate():
local = 50 # 局部变量,只在函数内可见
return total + local # 可以读取全局变量
print(calculate()) # 150
def modify_global():
global total # 声明要修改全局变量
total = 200 # 不加 global 会创建一个同名的局部变量
modify_global()
print(total) # 200
作用域规则一句话总结: 函数内可以读全局变量,但修改它必须用 global 声明;否则 Python 会认为你定义了一个同名局部变量。
四、参数类型全解析
Python 函数的参数系统灵活而强大,共有五种参数类型。掌握它们是写出优雅代码的关键。
4.1 位置参数
按顺序传递,最基础的传参方式。
def introduce(name, age, city):
print(f"我叫{name},今年{age}岁,来自{city}")
introduce("张三", 25, "北京")
# 我叫张三,今年25岁,来自北京
4.2 默认参数
给参数指定默认值,调用时可以不传。
def introduce(name, age, city="上海"):
print(f"我叫{name},今年{age}岁,来自{city}")
introduce("李四", 30) # city 用默认值
# 我叫李四,今年30岁,来自上海
introduce("王五", 28, "深圳") # 覆盖默认值
# 我叫王五,今年28岁,来自深圳
避坑: 默认参数的值只在函数定义时计算一次。切勿用可变对象(如列表、字典)做默认值!
# 错误示范
def add_item_wrong(item, target=[]):
target.append(item)
return target
print(add_item_wrong(1)) # [1]
print(add_item_wrong(2)) # [1, 2] ← 预期是 [2],但列表被复用了!
# 正确做法
def add_item_correct(item, target=None):
if target is None:
target = []
target.append(item)
return target
print(add_item_correct(1)) # [1]
print(add_item_correct(2)) # [2] ← 符合预期
4.3 关键字参数
调用时指定参数名,可以打乱顺序。
def order_info(name, product, quantity, price):
return f"{name} 购买了 {quantity} 件 {product},总价 {price * quantity} 元"
# 关键字参数:清晰且顺序无关
result = order_info(quantity=3, price=19.9, name="赵六", product="T恤")
print(result) # 赵六 购买了 3 件 T恤,总价 59.7 元
4.4 可变位置参数 *args
当你不知道函数会接收多少个位置参数时,用 *args 把它们打包成一个元组。
def sum_all(*args):
"""可以接收任意数量的参数"""
print(f"收到了 {len(args)} 个参数: {args}")
return sum(args)
print(sum_all(1, 2, 3)) # 收到了 3 个参数: (1, 2, 3) → 6
print(sum_all(10, 20, 30, 40)) # 收到了 4 个参数: (10, 20, 30, 40) → 100
4.5 可变关键字参数 **kwargs
当你不确定有多少个关键字参数时,用 **kwargs 把它们打包成一个字典。
def build_profile(name, **kwargs):
"""构建用户档案,支持任意额外信息"""
profile = {"name": name}
profile.update(kwargs)
return profile
user = build_profile("小明", age=18, city="广州", hobby="编程")
print(user)
# {'name': '小明', 'age': 18, 'city': '广州', 'hobby': '编程'}
4.6 参数组合使用的完整顺序
五种参数可以混合使用,但顺序是强制的:
def func(位置参数, *args, 默认参数, **kwargs)
def demo(a, b, *args, c=100, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"c={c}")
print(f"kwargs={kwargs}")
demo(1, 2, 3, 4, 5, c=200, x="hello", y="world")
# a=1, b=2
# args=(3, 4, 5)
# c=200
# kwargs={'x': 'hello', 'y': 'world'}
五种参数速查表:
| 位置参数 | name | 按顺序 | 是 |
| 默认参数 | name=value | 按顺序,可省略 | 否 |
| 可变位置 | *args | 打包成元组 | 否 |
| 关键字参数 | 调用时 key=value | 指定参数名 | 看定义 |
| 可变关键字 | **kwargs | 打包成字典 | 否 |
五、匿名函数 Lambda
Lambda 是 Python 中创建小型一次性函数的快捷方式,语法简洁,特别适合作为 map、filter、sorted 等高阶函数的参数。
5.1 Lambda 基础语法
# lambda 参数1, 参数2, … : 表达式(单行,自动返回)
# 普通函数写法
def add(a, b):
return a + b
# Lambda 写法
add_lambda = lambda a, b: a + b
print(add(3, 5)) # 8
print(add_lambda(3, 5)) # 8
Lambda 的核心限制:
- 只能包含一个表达式,不能有语句(不能赋值、不能有 if 语句块)
- 表达式的结果自动作为返回值
- 适合简单逻辑;复杂逻辑老老实实用 def
5.2 Lambda + map:批量变换
nums = [1, 2, 3, 4, 5]
# 每个元素平方
squared = list(map(lambda x: x ** 2, nums))
print(squared) # [1, 4, 9, 16, 25]
# 摄氏转华氏
celsius = [0, 10, 20, 30, 40]
fahrenheit = list(map(lambda c: c * 9/5 + 32, celsius))
print(fahrenheit) # [32.0, 50.0, 68.0, 86.0, 104.0]
5.3 Lambda + filter:条件筛选
nums = [12, 7, 25, 3, 18, 9, 30]
# 筛选偶数
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # [12, 18, 30]
# 筛选出长度 >= 3 的字符串
words = ["hi", "hello", "ok", "world", "go"]
long_words = list(filter(lambda w: len(w) >= 3, words))
print(long_words) # ['hello', 'world']
5.4 Lambda + sorted:自定义排序
students = [
{"name": "张三", "score": 85},
{"name": "李四", "score": 92},
{"name": "王五", "score": 78},
]
# 按分数排序
ranked = sorted(students, key=lambda s: s["score"], reverse=True)
print(ranked)
# [{'name': '李四', 'score': 92}, {'name': '张三', 'score': 85}, {'name': '王五', 'score': 78}]
# 按字符串长度排序
words = ["pineapple", "cat", "dog", "banana"]
sorted_words = sorted(words, key=lambda w: len(w))
print(sorted_words) # ['cat', 'dog', 'banana', 'pineapple']
5.5 Lambda vs def 对比
| 语句数量 | 多行,可含任意语句 | 仅一个表达式 |
| 名称 | 有函数名 | 匿名(通常不赋值给变量) |
| 可读性 | 复杂逻辑更清晰 | 简单逻辑更简洁 |
| 适用场景 | 常规函数定义 | map/filter/sorted 的 key 参数 |
| 文档字符串 | 支持 | 不支持 |
六、总结速查表
6.1 JSON / Pickle 操作速查
| 对象 → 字符串/字节 | json.dumps(obj) | pickle.dumps(obj) |
| 字符串/字节 → 对象 | json.loads(s) | pickle.loads(data) |
| 写入文件 | json.dump(obj, f) | pickle.dump(obj, f) |
| 从文件读取 | json.load(f) | pickle.load(f) |
| 文件模式 | "w" / "r"(文本) | "wb" / "rb"(二进制) |
| 中文处理 | ensure_ascii=False | 天然支持 |
6.2 函数参数速查
| 位置参数 | name | def f(a, b) |
| 默认参数 | name=value | def f(a, b=10) |
| *args | *args | def f(*args) → 元组 |
| **kwargs | **kwargs | def f(**kwargs) → 字典 |
| 关键字参数 | 调用时指定 | f(a=1, b=2) |
6.3 常用高阶函数
| map(fn, iterable) | 对每个元素应用 fn | map(lambda x: x*2, [1,2,3]) |
| filter(fn, iterable) | 筛选 fn 返回 True 的元素 | filter(lambda x: x>0, [-1,2,-3]) |
| sorted(it, key=fn) | 按 fn 的返回值排序 | sorted(lst, key=lambda x: x["age"]) |
**如果这篇文章对你有帮助,欢迎点赞、收藏、关注!有任何疑问欢迎在评论区留言交流,我会一一回复。你还想了解 Python 的哪个模块?

