目录

前言

一、Python 基础数据类型总览

二、字典(dict)核心基础规则

2.1 字典定义格式

2.2 两条硬性语法红线(必记)

2.3 字典的设计特点

三、字典三大遍历方式

实战:字符统计字典(统计字符串每个字符出现次数)

四、字典增删改查全套内置方法

4.1 修改 / 新增键值

4.2 删除元素

4.3 安全取值

4.4 快速创建字典

4.5 类型转换创建字典

五、JSON 序列化与文件持久化(字典落地本地文件)

5.1 核心概念区分

5.2 写入 JSON 文件两种写法

方式 1:dumps 先转字符串,再 write 写入

方式 2:dump 直接写入(with 上下文管理器,自动关闭文件,推荐)

5.3 读取 JSON 文件两种写法

方式 1:loads 读取文本后解析

方式 2:load 直接读取文件(推荐)

案例:复制库洛米图片

5.4、JSON 文件高频报错避坑指南

六.Python pickle模块详解

6.1 核心概念区分

6.2 dumps /loads 内存序列化(不操作文件)

6.3 dump /load 文件序列化(读写本地文件,你的学生管理系统可用)

6.4 方法对比总结

6.5 pickle VS json(高频面试考点)

6.6、使用注意事项


前言

字典(dict)是 Python 最核心的键值对容器,也是处理结构化数据、对接 JSON 文件的基础。日常开发里,字符统计、配置存储、接口数据解析、本地文件持久化都离不开字典 + JSON 组合。本文结合完整代码案例,一次性讲清字典底层规则、遍历、增删改查 API,以及 JSON 序列化 / 反序列化文件读写避坑要点。

一、Python 基础数据类型总览

Python 内置基础数据分为两大类:

  1. 单值类型(不可变) int整数、float浮点数、str字符串、bool布尔值
  2. 容器序列类型
  • list列表:有序可变数组,用数字下标取值
  • tuple元组:有序不可变数组,元素无法修改
  • dict字典:无序键值对映射,通过键快速检索(本文核心)

二、字典(dict)核心基础规则

2.1 字典定义格式

字典使用大括号{}包裹,格式 {键: 值, 键2: 值2},键和值支持绝大多数数据类型,但有严格限制。

python

运行

obj = {
    2: 1,               # int 做键
    3.4: 3.14,          # float 做键
    True: 666,          # bool 做键
    "key1": 10,         # str 最常用键
    "key2": "shuxudong",
    "key3": [1, 1, 3, 45],  # 值可以是列表
    (): 23,             # 元组(不可变)可以做键
    "addr": "无"
}

2.2 两条硬性语法红线(必记)

  1. 键必须是「不可变类型」 ✅ 合法键:int/float/str/tuple ❌ 非法键:list列表、dict字典(可变,运行直接报错)

    python

    运行

    # 报错示例,禁止使用
    obj = {[]: 55, {}: 66}
    
  2. 键不能重复 若定义重复键,只会保留最后一个重复键的值,前面同名键会被直接覆盖:

    python

    运行

    obj = {"key2": "shuxudong", "key2": "shu"}
    print(obj) # 输出 {'key2': 'shu'}
    

2.3 字典的设计特点

字典底层哈希表实现,通过键直接取值速度极快;代价是占用更多内存空间,属于「牺牲存储、换取查询速度」的数据结构。

三、字典三大遍历方式

遍历是业务高频操作,三种标准遍历 API 分别对应「只拿键、只拿值、同时拿键值」:

python

运行

obj = {"h":0, "e":0, "l":0, "o":0}

# 1. 只遍历所有键 obj.keys()
for k in obj.keys():
    print(k, obj[k])

# 2. 只遍历所有值 obj.values()
# 注意:只能拿值,无法反向通过值查找对应键
for v in obj.values():
    print(v)

# 3. 同时遍历键+值 obj.items()(最常用)
for k, v in obj.items():
    print(f"{k}:{v}")

实战:字符统计字典(统计字符串每个字符出现次数)

需求:遍历字符串,自动记录每个字符出现次数,无前置初始化字典:

python

运行

# 空字典,动态新增字符键
obj = {}
for e in "hello world":
    if e in obj:
        # 键已存在,计数+1
        obj[e] += 1
    else:
        # 键不存在,新建键,初始值=1
        obj[e] = 1
print(obj)
# 输出:{'h': 1, 'e': 1, 'l': 3, 'o': 2, ' ': 1, 'w': 1, 'r': 1, 'd': 1}

四、字典增删改查全套内置方法

4.1 修改 / 新增键值

  1. 下标直接赋值:存在则更新,不存在则新增

python

运行

obj["addr"] = "地点"
  1. update()批量更新,支持一次性修改多个键

python

运行

obj.update({"addr": "杭州", "name": "小明"})
# 注意:obj.update() 无返回值,变量接收会得到 None
b = obj.update({"addr": "地点"})
print(b) # None
  1. setdefault():键不存在才新增,已存在则不修改

python

运行

# addr已有值,不会覆盖;无addr则新增默认值"杭"
obj.setdefault("addr", "杭")

4.2 删除元素

  1. pop(键):删除指定键,返回被删除的值,键不存在直接报错

python

运行

r = obj.pop(2)
print(r, obj)
  1. popitem():删除最后插入的一组键值对(Python3.7 + 字典有序)

python

运行

r = obj.popitem()
  1. clear():清空字典所有内容,保留空字典对象

python

运行

obj.clear()

4.3 安全取值

get(键, 默认值):键存在返回对应值,不存在返回None(或自定义默认值),不会抛KeyError,生产环境推荐替代obj["key"]

python

运行

print(obj.get("key1"))
print(obj.get("test", 0)) # 无test键,返回0

4.4 快速创建字典

dict.fromkeys(键列表, 统一值):批量生成多键字典,所有键初始值相同

python

运行

d0 = dict.fromkeys(["key1", "key2", "key3"], 222)
print(d0) # {'key1': 222, 'key2': 222, 'key3': 222}

4.5 类型转换创建字典

dict()支持接收「嵌套二元序列」生成字典,每一组子序列必须只有 2 个元素(键、值):

python

运行

# 列表嵌套列表
d = dict([["key1", range(10)], ["key3", "按键3"]])
# 元组嵌套元组
d = dict(((1,2), (2,1)))

五、JSON 序列化与文件持久化(字典落地本地文件)

5.1 核心概念区分

表格

函数 作用 使用场景
json.dumps() 序列化:Python 字典 / 列表 → JSON 字符串 纯内存处理字符串
json.loads() 反序列化:JSON 字符串 → Python 字典 / 列表 纯内存解析字符串
json.dump() 序列化写入文件:Python 数据直接存 txt 本地持久化(最常用)
json.load() 读取文件反序列化:读取 txt 转为 Python 数据 读取本地存储数据

5.2 写入 JSON 文件两种写法

案例:将学生信息保存到文件中

student = [
    {
        "student_id": 1,
        "name": "张三",
    },

    {
        "student_id": 2,
        "name": "赵四",
    },

    {
        "student_id": 3,
        "name": "关六",
    }

]


方式 1:dumps 先转字符串,再 write 写入

python

运行

import json
# 方式1
# 将学生信息写入文件中
student_str = json.dumps(student,ensure_ascii=False)
f = open("date.txt", "w",encoding="utf-8")
f.write(student_str)
f.close()

方式 2:dump 直接写入(with 上下文管理器,自动关闭文件,推荐)

python

运行

import json
with open('date.txt', 'w',encoding="utf-8") as f:
    # 写入内容 文件 不转换中文
    json.dump(student, f, ensure_ascii=False)
f.close()
  • ensure_ascii=False 关键参数:解决中文乱码,不加中文会变成\uXXXX编码

5.3 读取 JSON 文件两种写法

方式 1:loads 读取文本后解析

python

运行

# 读取学生文件信息
# 方式1
f = open("date.txt", "r",encoding="utf-8")
student_list = json.loads(f.read())
print(student_list)
f.close()

方式 2:load 直接读取文件(推荐)

python

运行

with open('date.txt', 'r',encoding="utf-8") as f:
    student_list = json.load(f)
print(student_list)
f.close()

案例:复制库洛米图片

with open('飞行库洛米.png', 'rb') as f:
    with open("飞行库洛米new.png", "wb") as f1:
        f1.write(f.read())
f1.close()
f.close()

5.4、JSON 文件高频报错避坑指南

  1. JSONDecodeError: Expecting value: line1 column1 原因:txt 文件空白、无任何 JSON 内容;解决方案:文件写入标准空容器{}(字典)/[](列表),代码增加try-except捕获异常,空文件自动赋值空字典。

  2. TypeError: list indices must be integers or slices, not str 原因:文件存储[]列表,读取后赋值给本应是字典的变量,用字符串下标取值;解决方案:统一业务存储为{}字典,读取后判断数据类型,列表自动转为空字典。

  3. JSONDecodeError: Extra data 原因:文件每行一条独立 JSON,不是一整块数组 / 字典;解决方案:文件外层包裹[]合并成单个数组,或逐行循环json.loads()解析。

  4. 中文乱码 解决方案:json.dump/dumps必须添加ensure_ascii=False,打开文件统一指定encoding="utf-8"

六.Python pickle模块详解

pickle 是 Python 内置序列化模块,能够将 Python 对象转为二进制字节流,也可以从字节 / 文件还原出原始对象。注意:pickle 仅适用于 Python,无法和 Java、JS 等其他语言互通,不适合跨语言数据交互。

6.1 核心概念区分

  • 序列化:对象 → 二进制字节

    • dumps():对象 → 二进制字节(内存操作)

    • dump():对象 → 二进制并直接写入文件

  • 反序列化:二进制字节 → Python 对象

    • loads():二进制字节 → 对象

    • load():读取二进制文件 → 对象

⚠️ 安全警告:不要反序列化来源不明的数据,恶意二进制数据会执行危险代码!

6.2 dumps /loads 内存序列化(不操作文件)

python

运行

import pickle

# 原始对象(列表、字典、自定义数据都可以)
user_list = [
    {"name":"瓜瓜", "age":18},
    {"name":"小明", "age":16}
]

# 序列化:对象 → 二进制字节
byte_data = pickle.dumps(user_list)
print(byte_data)

# 反序列化:字节 → Python对象
obj = pickle.loads(byte_data)
print(obj)
print(type(obj))

6.3 dump /load 文件序列化

python

运行

import pickle

user_list = [
    {"name":"瓜瓜", "age":18},
    {"name":"小明", "age":16}
]

# dump:序列化并写入文件,文件必须使用 wb 二进制写入模式
with open("user.data", "wb") as f:
    pickle.dump(user_list, f)

# load:读取二进制文件,还原对象,文件必须使用 rb 二进制读取模式
with open("user.data", "rb") as f:
    data = pickle.load(f)

print(data)

6.4 方法对比总结

表格

方法 作用 操作目标
pickle.dumps() 序列化 内存,返回 bytes
pickle.dump() 序列化 直接写入文件
pickle.loads() 反序列化 读取 bytes 字节
pickle.load() 反序列化 读取二进制文件

6.5 pickle VS json(高频面试考点)

  1. json:跨语言,只能序列化字符串、数字、列表、字典基础类型;
  2. pickle:仅 Python 可用,支持列表、字典、元组、类实例等几乎所有 Python 对象;
  3. json 是人可读文本;pickle 是二进制,无法直接打开阅读。

6.6、使用注意事项

  1. 文件打开模式必须带 bwb / rb(二进制模式);
  2. 无法跨语言交互,跨语言传输优先使用 JSON;
  3. 禁止加载网络上未知来源的 pickle 文件,存在安全漏洞;
  4. 不同大版本 Python 之间 pickle 兼容性可能存在问题。

七、Python copy 模块:浅拷贝与深拷贝详解

在 Python 中,变量赋值本质是内存地址引用。当存在嵌套可变对象时,直接赋值会引发数据联动修改问题。copy模块提供浅拷贝copy()深拷贝deepcopy(),用来实现对象复制,解决引用共享问题。本文结合多层嵌套列表案例,清晰区分深浅拷贝,梳理底层原理与使用场景。

前置知识点

  1. id():获取对象内存地址,用来判断是否为同一个对象;
  2. 可变类型:listdictset;不可变类型:intstrtuple
  3. 单纯等号赋值:引用传递,多个变量指向同一块内存。

7.1 引用赋值(区分拷贝,先看懂误区)

python

运行

d = [1,2,3,4,5]
d1 = d
print(id(d), id(d1))
# 二者id完全相同,指向同一个列表
d.append(6)
print(d)
print(d1)
# 原列表修改,d1同步变化

原理:d1=d没有创建新对象,仅仅复制内存地址,属于引用别名。

7.2 浅拷贝 copy.copy ()

原理

创建一层全新容器;

  • 不可变子对象:直接复用引用;

  • 可变嵌套子对象:依旧复用原始内存地址。 👉 结论:多层嵌套结构,内层可变对象数据不独立!

实现浅拷贝的多种方式

  1. copy.copy()

  2. 列表切片 lst[:]

  3. list()dict()类型转换

  4. 列表内置方法 .copy()

案例演示

python

运行

import copy

# 嵌套列表(外层list,内层还有子list)
d0 = [1, 2, 3, ["a", "b", "c"]]
d1 = copy.copy(d0)

print(id(d0))
print(id(d1))
# ✅ 外层容器:内存地址不同(新列表)

print(id(d0[3]))
print(id(d1[3]))
# ❗嵌套内层列表:地址完全一致,共享同一个子列表

# 修改内层可变对象
d0[3].append("d")
print(d0)
print(d1)
# d0、d1内层数据同时变化!

其他浅拷贝写法演示

python

运行

d0 = [1, 2, 3, ["a", "b", "c"]]
d2 = d0[:]       # 切片浅拷贝
d3 = list(d0)    # list转换浅拷贝

7.3深拷贝 copy.deepcopy ()

原理

递归复制所有层级对象,无论外层容器、嵌套的可变子对象,全部开辟全新内存地址。 👉 结论:拷贝后的对象和原始对象完全独立,任意层级修改互不影响。

python

运行

import copy

d0 = [1, 2, 3, ["a", "b", "c"]]
d4 = copy.deepcopy(d0)

print(id(d0))
print(id(d4))
print(id(d0[3]))
print(id(d4[3]))
# 外层、内层子列表地址全部不同

# 修改原对象
d0.append(4)
d0[3].append("d")

print("原始d0:", d0)
print("深拷贝d4:", d4)
# d4不受任何影响

7.4 浅拷贝 VS 深拷贝核心对比

表格

方式 特点 嵌套可变对象 性能
浅拷贝 copy () 只拷贝第一层容器 内层可变对象共享引用 快,开销小
深拷贝 deepcopy () 递归拷贝所有层级 所有层级完全独立 较慢,数据量大开销高

7.5 使用场景建议

  1. 对象没有嵌套可变类型:优先浅拷贝,性能更好;
  2. 对象存在多层嵌套列表 / 字典,修改时需要数据隔离:使用深拷贝;
  3. 不要直接使用等号赋值,如果需要独立副本务必拷贝;

7.6 常见面试总结金句

浅拷贝仅复制第一层容器,嵌套可变对象依旧共用内存;深拷贝递归拷贝全部层级,原始对象与副本完全隔离。深拷贝会带来额外性能开销,业务开发根据嵌套结构合理选择,不要无脑使用deepcopy

⚠️补充注意

  1. 不可变对象(数字、字符串)拷贝一般无意义;
  2. 深拷贝可以处理多层嵌套,但不适合超大循环嵌套对象,容易占用大量内存;
  3. 循环引用对象,deepcopy 可以正常处理。

    Logo

    这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

    更多推荐