Python3基础:吃透容器数据类型,高效处理海量数据

6 阅读28分钟

第四阶段:吃透容器数据类型,高效处理海量数据

😄生命不息,写作不止

🔥 继续踏上学习之路,学之分享笔记

👊 总有一天我也能像各位大佬一样

🏆 博客首页   @怒放吧德德  To记录领地 @一个有梦有戏的人

🌝分享学习心得,欢迎指正,大家一起学习成长!

🔥豆包AI

转发请携带作者信息  @怒放吧德德(掘金) @一个有梦有戏的人(CSDN)

前言

恭喜大家顺利通关Python3基础学习第三阶段!在第三阶段,我们掌握了流程控制的核心逻辑,让程序能够“有判断、有重复”地执行。而第四阶段我们要学习的「容器数据类型」,就像是程序的“数据仓库”——它能帮助我们高效存储、组织和管理大量数据,解决单一变量无法存储多个数据的痛点,同时衔接流程控制知识点,实现更灵活、更高效的数据处理。

本次第四阶段,我们重点攻克五大核心内容:列表(List)、元组(Tuple)、字典(Dictionary)、集合(Set),以及字符串高级操作。每一个知识点都搭配可直接复制运行的代码示例、详细解析和新手避坑技巧,全程贴合新手学习节奏,跟着敲代码、练案例,就能轻松掌握这些“数据仓库”的使用方法,为后续更复杂的编程学习筑牢基础~

1 列表(List):最灵活的“有序数据仓库”

列表是Python中最常用、最灵活的容器类型,核心特点是「有序、可变、可存储任意类型数据」——可以理解为一个“可随时增减、可修改内容的有序文件夹”,既能存储多个相同类型的数据,也能存储混合类型的数据,是日常编程中使用频率最高的容器。

我们从“创建→访问→增删改查→切片→常用方法”逐步拆解,每一步都搭配代码示例,新手可直接复制运行。

1.1 列表的创建(3种常用方式)

列表用方括号 [] 表示,元素之间用逗号分隔;也可通过 list() 函数创建,两种方式按需选择,基础创建非常简单。

# 方式1:直接用方括号创建(最常用)
# 1.1 创建空列表
empty_list = []
print(empty_list)  # 输出:[]
print(type(empty_list))  # 输出:<class 'list'>

# 1.2 创建包含元素的列表(单一类型)
num_list = [1, 2, 3, 4, 5]  # 整数列表
str_list = ["Python", "Java", "C++"]  # 字符串列表

# 1.3 创建包含混合类型元素的列表(列表特色)
mixed_list = [10, "Python", True, 3.14, [1, 2, 3]]  # 包含列表(嵌套列表)
print(mixed_list)  # 输出:[10, 'Python', True, 3.14, [1, 2, 3]]

# 方式2:用list()函数创建(适合转换其他数据类型)
# 将字符串转为列表(每个字符作为元素)
str_to_list = list("Python")
print(str_to_list)  # 输出:['P', 'y', 't', 'h', 'o', 'n']

# 将元组转为列表(数组中可以是不同类型的)
tuple_to_list = list((1, 2, 3))
print(tuple_to_list)  # 输出:[1, 2, 3]

# 将range对象转为列表
range_to_list = list(range(1, 6))
print(range_to_list)  # 输出:[1, 2, 3, 4, 5]

新手避坑:创建嵌套列表时,内层列表需用方括号包裹,访问时需用多级索引;用list()函数转换时,参数需是可迭代对象(字符串、元组、range等)。

1.2 列表的访问(索引访问,与字符串一致)

列表是有序容器,每个元素都有唯一的「索引」(位置编号),可通过索引访问单个元素,支持正向索引(从0开始)和反向索引(从-1开始),与第三阶段学习的字符串索引逻辑完全一致。

fruits = ["苹果", "香蕉", "橙子", "葡萄", "芒果"]

# 正向索引:从0开始,0是第一个元素
print(fruits[0])  # 输出:苹果(第一个元素)
print(fruits[2])  # 输出:橙子(第三个元素)

# 反向索引:从-1开始,-1是最后一个元素
print(fruits[-1])  # 输出:芒果(最后一个元素)
print(fruits[-3])  # 输出:橙子(倒数第三个元素)

# 访问嵌套列表的元素(多级索引)
mixed_list = [10, ["a", "b", "c"], 30]
print(mixed_list[1])  # 输出:['a', 'b', 'c'](访问内层列表)
print(mixed_list[1][2])  # 输出:c(访问内层列表的第三个元素)

# 注意:索引不能超出列表范围,否则报错
# print(fruits[5])  # 报错:IndexError(列表长度为5,索引最大为4)

技巧:可通过 len() 函数获取列表长度,避免索引越界,如 print(len(fruits)) 可获取列表长度5。

  1. 反向索引是语法糖:Python解释器在遇到负索引时自动转换为正索引
  2. 时间复杂度:反向索引访问和正向索引一样,都是O(1)操作
  3. 广泛适用:不仅列表,元组、字符串等序列类型都支持反向索引
  4. 边界检查:转换后仍然会检查索引是否在有效范围内

1.3 列表的增删改查(核心操作,重点掌握)

列表的核心优势是「可变」,可随时添加、删除、修改元素,这也是它与后续要学的元组最本质的区别。我们分四个操作逐一讲解,每个操作都给出最常用的方法。

1.3.1 增:给列表添加元素(3种常用方法)
nums = [1, 2, 3]

# 方法1:append(x):在列表末尾添加单个元素(最常用)
nums.append(4)
print(nums)  # 输出:[1, 2, 3, 4]
nums.append(5)
print(nums)  # 输出:[1, 2, 3, 4, 5]

# 方法2:insert(index, x):在指定索引位置插入元素
nums.insert(2, 2.5)  # 在索引2的位置插入2.5
print(nums)  # 输出:[1, 2, 2.5, 3, 4, 5]

# 方法3:extend(lst2):将另一个列表的所有元素添加到当前列表末尾(批量添加)
nums2 = [6, 7, 8]
nums.extend(nums2)
print(nums)  # 输出:[1, 2, 2.5, 3, 4, 5, 6, 7, 8]

# 避坑:append与extend的区别
nums.append(nums2)  # 会将nums2作为一个整体元素添加
print(nums)  # 末尾会多一个[6,7,8],而非单个元素
1.3.2 删:删除列表中的元素(4种常用方法)
fruits = ["苹果", "香蕉", "橙子", "葡萄", "芒果"]

# 方法1:remove(x):根据元素值删除,删除第一个匹配的元素
fruits.remove("橙子")
print(fruits)  # 输出:['苹果', '香蕉', '葡萄', '芒果']

# 方法2:pop(index):根据索引删除元素,默认删除最后一个,返回被删除的元素
deleted_fruit = fruits.pop()  # 不指定索引,删除最后一个
print(deleted_fruit)  # 输出:芒果
print(fruits)  # 输出:['苹果', '香蕉', '葡萄']
fruits.pop(1)  # 指定索引1,删除第二个元素
print(fruits)  # 输出:['苹果', '葡萄']

# 方法3:del 语句:根据索引删除,也可删除整个列表(彻底删除)
del fruits[0]  # 删除索引0的元素
print(fruits)  # 输出:['葡萄']
# del fruits  # 彻底删除列表,后续无法访问fruits

# 方法4:clear():清空列表所有元素,保留列表对象(变为空列表)
fruits.clear()
print(fruits)  # 输出:[]

新手避坑:remove(x)删除不存在的元素会报错;pop(index)指定超出范围的索引会报错;del语句彻底删除列表后,后续访问会报错。

1.3.3 改:修改列表中的元素(直接通过索引赋值)
nums = [1, 2, 3, 4, 5]

# 修改单个元素:索引赋值
nums[2] = 30  # 将索引2的元素改为30
print(nums)  # 输出:[1, 2, 30, 4, 5]

# 修改嵌套列表的元素
mixed_list = [10, ["a", "b", "c"], 30]
mixed_list[1][1] = "x"  # 修改内层列表的元素
print(mixed_list)  # 输出:[10, ['a', 'x', 'c'], 30]

# 批量修改:切片赋值(后续切片部分详细讲解)
nums[1:3] = [20, 300]
print(nums)  # 输出:[1, 20, 300, 4, 5]
1.3.4 查:查询列表中的元素(判断存在+查找索引+统计次数)
fruits = ["苹果", "香蕉", "葡萄", "香蕉", "芒果"]

# 1. 判断元素是否存在:in / not in(返回布尔值)
print("香蕉" in fruits)  # 输出:True(存在)
print("橙子" not in fruits)  # 输出:True(不存在)

# 2. 查找元素索引:index(x):返回第一个匹配元素的索引,不存在报错
print(fruits.index("香蕉"))  # 输出:1(第一个香蕉的索引)

# 3. 统计元素出现次数:count(x):返回元素x在列表中出现的次数
print(fruits.count("香蕉"))  # 输出:2(香蕉出现2次)

1.4 列表的切片(灵活获取子列表,与字符串切片一致)

切片是列表的高级访问方式,可快速获取列表中的一个「子列表」,语法与字符串切片完全一致:列表名[起始索引:结束索引:步长],核心规则:左闭右开(包含起始索引,不包含结束索引),步长默认1。

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 1. 基础切片:起始索引:结束索引(步长默认1)
print(nums[2:6])  # 输出:[2, 3, 4, 5](包含2,不包含6)
print(nums[:5])   # 输出:[0, 1, 2, 3, 4](起始索引省略,默认从0开始)
print(nums[5:])   # 输出:[5, 6, 7, 8, 9](结束索引省略,默认到末尾)
print(nums[:])    # 输出:[0, 1, 2, ..., 9](省略所有,复制整个列表)

# 2. 指定步长切片
print(nums[0:10:2])  # 输出:[0, 2, 4, 6, 8](步长为2,间隔1个元素)
print(nums[10:0:-2]) # 输出:[9, 7, 5, 3, 1](步长为负,反向切片)

# 3. 反向切片(快速反转列表)
print(nums[::-1])    # 输出:[9, 8, 7, ..., 0](步长为-1,反转整个列表)

# 4. 切片赋值(批量修改/添加/删除)
nums[2:4] = [20, 30]  # 替换切片对应的元素
print(nums)  # 输出:[0, 1, 20, 30, 4, 5, 6, 7, 8, 9]
nums[5:7] = []  # 赋值为空列表,等价于删除该切片元素
print(nums)  # 输出:[0, 1, 20, 30, 4, 7, 8, 9]

1.5 列表的常用方法(高频使用,必记)

除了上述增删改查和切片,列表还有几个高频常用方法,搭配代码理解,重点记功能和用法:

nums = [3, 1, 4, 1, 5, 9, 2, 6]

# 1. sort():对列表进行排序,默认升序,修改原列表
nums.sort()
print(nums)  # 输出:[1, 1, 2, 3, 4, 5, 6, 9]
# 降序排序:reverse=True
nums.sort(reverse=True)
print(nums)  # 输出:[9, 6, 5, 4, 3, 2, 1, 1]

# 2. reverse():反转列表元素顺序,修改原列表
nums.reverse()
print(nums)  # 输出:[1, 1, 2, 3, 4, 5, 6, 9]

# 3. copy():复制列表,返回新列表(避免修改原列表)
nums2 = nums.copy()
nums2[0] = 100
print(nums)   # 输出:[1, 1, 2, 3, 4, 5, 6, 9](原列表不变)
print(nums2)  # 输出:[100, 1, 2, 3, 4, 5, 6, 9](新列表修改)

# 4. len():获取列表长度(元素个数)
print(len(nums))  # 输出:8

# 5. max()/min():获取列表中的最大值/最小值(仅适用于数字列表)
print(max(nums))  # 输出:9
print(min(nums))  # 输出:1

2 元组(Tuple):不可变的“安全数据仓库”

元组与列表非常相似,核心特点是「有序、不可变、可存储任意类型数据」——可以理解为一个“一旦创建就无法修改内容的有序文件夹”,适合存储不需要变更的数据(如固定配置、坐标等),安全性更高。

元组的语法和用法与列表大部分一致,重点掌握「不可变特性」和与列表的区别即可。

与 jdk 9 的 List.of(...) 类似

2.1 元组的创建(2种常用方式)

元组用圆括号 () 表示,元素之间用逗号分隔;也可通过 tuple() 函数创建,注意单元素元组的特殊写法。

# 方式1:直接用圆括号创建(最常用)
# 1.1 创建空元组
empty_tuple = ()
print(empty_tuple)  # 输出:()
print(type(empty_tuple))  # 输出:<class 'tuple'>

# 1.2 创建包含元素的元组
num_tuple = (1, 2, 3, 4, 5)
str_tuple = ("Python", "Java", "C++")
mixed_tuple = (10, "Python", True, 3.14)  # 混合类型

# 1.3 单元素元组(关键细节:必须加逗号,否则会被识别为普通类型)
t1 = (10)  # 错误:被识别为整数
print(type(t1))  # 输出:<class 'int'>
t2 = (10,)  # 正确:加逗号,被识别为元组
t3 = 20,  # 省略括号,同样需要加逗号
print(type(t2), type(t3))  # 输出:<class 'tuple'> <class 'tuple'>

# 方式2:用tuple()函数创建(转换其他可迭代对象)
str_to_tuple = tuple("Python")
print(str_to_tuple)  # 输出:('P', 'y', 't', 'h', 'o', 'n')
list_to_tuple = tuple([1, 2, 3])
print(list_to_tuple)  # 输出:(1, 2, 3)

2.2 元组的核心特性:不可变性(重点!)

元组与列表最本质的区别:元组一旦创建,其元素的个数、值、顺序都无法修改(包括添加、删除、替换元素),尝试修改会直接报错,这就是元组的“不可变性”,能有效保护数据安全。

t = (1, 2, 3, 4)

# 尝试修改元素(报错)
# t[0] = 10  # 报错:TypeError(元组不支持元素赋值)

# 尝试添加元素(报错)
# t.append(5)  # 报错:AttributeError(元组没有append方法)

# 尝试删除元素(报错)
# del t[1]  # 报错:TypeError(元组不支持元素删除)
# t.pop()  # 报错:AttributeError(元组没有pop方法)

# 不可变性的例外:若元组包含可变元素(如列表),可变元素内部可修改
t = (1, ["a", "b", "c"], 3)
# 无法修改元组中元素的引用(如替换列表)
# t[1] = ["x", "y"]  # 报错
# 可修改列表内部的内容
t[1].append("d")
print(t)  # 输出:(1, ['a', 'b', 'c', 'd'], 3)

2.3 元组的使用(访问、查询,与列表一致)

元组的访问、查询方法与列表完全一致,支持索引访问、切片、in/not in、index()、count(),因为这些操作不会修改元组本身。

t = ("苹果", "香蕉", "橙子", "香蕉", "芒果")

# 1. 索引访问
print(t[0])  # 输出:苹果
print(t[-1])  # 输出:芒果

# 2. 切片
print(t[1:4])  # 输出:('香蕉', '橙子', '香蕉')
print(t[::-1])  # 输出:('芒果', '香蕉', '橙子', '香蕉', '苹果')

# 3. 查询操作
print("香蕉" in t)  # 输出:True
print(t.index("橙子"))  # 输出:2
print(t.count("香蕉"))  # 输出:2

# 4. 常用内置函数
print(len(t))  # 输出:5(长度)
print(max(["a", "b", "c"]))  # 输出:c(字符串元组可比较)

2.4 元组与列表的区别(必记,新手不混淆)

  • 语法区别:列表用 [],元组用 (),单元素元组需加逗号;
  • 核心区别:列表「可变」(可增删改),元组「不可变」(不可增删改);
  • 方法区别:列表有append、insert、remove等修改方法,元组只有查询方法;
  • 使用场景:列表适合存储需要动态修改的数据,元组适合存储固定不变的数据(如坐标、配置),元组可作为字典的键(列表不可)。

3. *字典(Dictionary):键值对的“映射数据仓库”

字典是Python中最灵活的「映射型容器」,核心特点是「无序(Python3.7+后有序)、可变、键值对存储」——可以理解为一个“带标签的文件夹”,每个元素都由“键(key,标签)”和“值(value,内容)”组成,通过键快速查找值,无需通过索引,查询效率极高,常用于存储关联数据(如用户信息、配置参数)。(非常重要),与 Java 的 hashmap 类似,对比表如下:

特性Python <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">dict</font>Java <font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">HashMap</font>是否相似
数据结构哈希表哈希表完全相同
时间复杂度O(1) 平均查找/插入/删除O(1) 平均查找/插入/删除完全相同
键唯一性键必须唯一键必须唯一完全相同
允许null键允许(Python中是<font style="color:rgb(15, 17, 21);background-color:rgb(235, 238, 242);">None</font>
允许(1个null键)相似
允许null值允许允许(多个null值)相似
无序性Python 3.6前无序,3.7+保持插入顺序Java 8前无序,Java 8+保持一定顺序相似
动态扩容自动扩容自动扩容(负载因子0.75)相似
冲突解决开放寻址法链表/红黑树(Java 8+)⚠️ 不同

3.1 字典的创建(2种常用方式)

字典用大括号 {} 表示,每个元素是 键:值 的形式,键值对之间用逗号分隔;也可通过 dict() 函数创建,键必须是不可变类型(字符串、数字、元组),值可任意类型。

# 方式1:直接用大括号创建(最常用)
# 1.1 创建空字典
empty_dict = {}
print(empty_dict)  # 输出:{}
print(type(empty_dict))  # 输出:<class 'dict'>

# 1.2 创建包含键值对的字典(关联数据)
user_info = {
    "name": "张三",
    "age": 18,
    "gender": "男",
    "score": 95.5
}
print(user_info)  # 输出:{'name': '张三', 'age': 18, 'gender': '男', 'score': 95.5}

# 1.3 嵌套字典(值为字典)
student_info = {
    "张三": {"age": 18, "score": 95},
    "李四": {"age": 19, "score": 88}
}

# 方式2:用dict()函数创建
dict1 = dict(name="李四", age=19, gender="女")  # 关键字参数形式
dict2 = dict([("name", "王五"), ("age", 20)])  # 列表嵌套元组形式
print(dict1)  # 输出:{'name': '李四', 'age': 19, 'gender': '女'}
print(dict2)  # 输出:{'name': '王五', 'age': 20}

# 新手避坑:键必须是不可变类型,值可任意类型
# invalid_dict = {[1,2]: "错误"}  # 报错:列表是可变类型,不能作为键

3.2 字典的核心:键(key)的规则(必记)

字典的键是唯一的“标签”,必须遵循3个规则,否则会报错或出现异常[superscript:1]:

  • 键必须是「不可变类型」:字符串、数字、元组(不可变)均可,列表、集合(可变)不可作为键;
  • 键必须「唯一」:若出现重复键,后面的键值对会覆盖前面的(不会报错,但会丢失数据);
  • 键区分大小写:如 "Name" 和 "name" 是两个不同的键。
# 重复键:后面覆盖前面
dict1 = {"name": "张三", "name": "李四"}
print(dict1)  # 输出:{'name': '李四'}(前面的张三被覆盖)

# 区分大小写
dict2 = {"name": "张三", "Name": "李四"}
print(dict2)  # 输出:{'name': '张三', 'Name': '李四'}(两个不同的键)

3.3 字典的增删改查(核心操作,重点掌握)

字典的增删改查均围绕「键(key)」展开,无需使用索引,操作逻辑比列表更简洁,重点掌握常用方法。

(1)增:添加键值对(2种常用方式)
user_info = {"name": "张三", "age": 18}

# 方法1:直接通过键赋值(最常用)
# 键不存在:添加新键值对
user_info["gender"] = "男"
print(user_info)  # 输出:{'name': '张三', 'age': 18, 'gender': '男'}
# 键存在:修改值(后续修改操作)
user_info["age"] = 19
print(user_info)  # 输出:{'name': '张三', 'age': 19, 'gender': '男'}

# 方法2:update()方法:批量添加/修改键值对
# 传入字典,存在的键修改值,不存在的键添加
user_info.update({"score": 95.5, "address": "北京"})
print(user_info)  # 新增score和address两个键值对

# 方法3:setdefault(key, default):键不存在则添加,存在则不修改
user_info.setdefault("hobby", "编程")  # 新增hobby键值对
user_info.setdefault("name", "李四")  # name已存在,不修改
print(user_info)  # 输出包含hobby: '编程'
(2)删:删除键值对(4种常用方法)
user_info = {"name": "张三", "age": 18, "gender": "男", "score": 95.5}

# 方法1:del 语句:根据键删除,删除不存在的键报错
del user_info["gender"]
print(user_info)  # 输出:{'name': '张三', 'age': 18, 'score': 95.5}
# del user_info["address"]  # 报错:KeyError(address不存在)

# 方法2:pop(key, default):根据键删除,返回被删除的值,不存在则返回默认值(安全)
deleted_score = user_info.pop("score")
print(deleted_score)  # 输出:95.5
print(user_info)  # 输出:{'name': '张三', 'age': 18}
# 不存在的键,返回默认值,不报错
user_info.pop("address", "未知")  # 返回:未知,不报错

# 方法3:popitem():删除最后一个键值对(Python3.7+),返回被删除的键值对
deleted_item = user_info.popitem()
print(deleted_item)  # 输出:('age', 18)
print(user_info)  # 输出:{'name': '张三'}

# 方法4:clear():清空字典所有键值对,保留字典对象
user_info.clear()
print(user_info)  # 输出:{}
(3)改:修改键值对(直接通过键赋值,最常用)
user_info = {"name": "张三", "age": 18, "score": 95}

# 直接通过键赋值:键存在则修改值,不存在则添加
user_info["age"] = 19  # 修改age的值
user_info["score"] = 98  # 修改score的值
print(user_info)  # 输出:{'name': '张三', 'age': 19, 'score': 98}

# 批量修改:update()方法
user_info.update({"age": 20, "score": 100})
print(user_info)  # 输出:{'name': '张三', 'age': 20, 'score': 100}
(4)查:查询键值对(3种常用方式,重点掌握)
user_info = {"name": "张三", "age": 18, "gender": "男", "score": 95.5}

# 方法1:直接通过键访问(最常用),键不存在报错
print(user_info["name"])  # 输出:张三
print(user_info["age"])   # 输出:18
# print(user_info["address"])  # 报错:KeyError(address不存在)

# 方法2:get(key, default):通过键访问,键不存在返回默认值(安全,最推荐)
print(user_info.get("name"))  # 输出:张三
print(user_info.get("address", "未知"))  # 输出:未知(不存在,返回默认值)

# 方法3:查询所有键、所有值、所有键值对
print(user_info.keys())    # 输出:dict_keys(['name', 'age', 'gender', 'score'])(所有键)
print(user_info.values())  # 输出:dict_values(['张三', 18, '男', 95.5])(所有值)
print(user_info.items())   # 输出:dict_items([('name', '张三'), ...])(所有键值对,可用于遍历)

# 遍历字典(结合第三阶段for循环,重点应用)
for key in user_info.keys():
    print(f"键:{key},值:{user_info[key]}")
for key, value in user_info.items():
    print(f"键:{key},值:{value}")

3.4 字典的常用方法(高频使用)

# 1. keys()/values()/items():查询所有键、值、键值对(如上查询部分)
# 2. get(key, default):安全访问值(最常用)
# 3. update():批量增删改
# 4. setdefault(key, default):安全添加键值对
# 5. copy():复制字典(避免修改原字典)
dict1 = {"name": "张三", "age": 18}
dict2 = dict1.copy()
dict2["age"] = 19
print(dict1)  # 输出:{'name': '张三', 'age': 18}(原字典不变)
print(dict2)  # 输出:{'name': '张三', 'age': 19}(新字典修改)

4 集合(Set):去重优先的“无序数据仓库”

集合是Python中「无序、可变、唯一」的容器类型,核心特点是「自动去重、支持集合运算」——可以理解为一个“无标签、不重复的文件夹”,适合用于去重、判断元素是否存在、集合之间的交集/并集等操作,查询效率比列表高。

4.1 集合的创建(2种常用方式)

集合用大括号{} 表示,元素之间用逗号分隔;也可通过set() 函数创建,注意:创建空集合必须用set(),不能用{}({}创建的是空字典)

# 方式1:直接用大括号创建(元素唯一,自动去重)
# 1.1 创建包含元素的集合
num_set = {1, 2, 3, 4, 4, 5}  # 包含重复元素
print(num_set)  # 输出:{1, 2, 3, 4, 5}(自动去重)
str_set = {"Python", "Java", "Python"}
print(str_set)  # 输出:{'Python', 'Java'}(自动去重)

# 1.2 注意:不能用{}创建空集合(创建的是空字典)
empty_set1 = {}
print(type(empty_set1))  # 输出:<class 'dict'>(空字典)

# 方式2:用set()函数创建(最常用,适合转换其他类型去重)
# 创建空集合(正确方式)
empty_set2 = set()
print(empty_set2)  # 输出:set()
print(type(empty_set2))  # 输出:<class 'set'>

# 转换其他可迭代对象,自动去重
list_to_set = set([1, 2, 2, 3, 4])
print(list_to_set)  # 输出:{1, 2, 3, 4}(列表去重)
str_to_set = set("Python")
print(str_to_set)  # 输出:{'P', 'y', 't', 'h', 'o', 'n'}(字符串去重,无序)

新手避坑:集合是无序的,无法通过索引访问元素;创建空集合必须用set(),{}创建的是空字典。

4.2 集合的核心特性:自动去重(重点!)

集合的最常用场景就是「去重」——无论创建时是否包含重复元素,集合都会自动保留唯一元素,无需手动处理,这是集合最核心的优势。

# 案例1:列表去重(最常用场景)
original_list = [1, 2, 2, 3, 3, 3, 4, 5, 5]
# 列表转集合,自动去重,再转回列表
unique_list = list(set(original_list))
print(unique_list)  # 输出:[1, 2, 3, 4, 5](去重后的列表,顺序可能变化)

# 案例2:字符串去重
original_str = "aabbbccc"
unique_str = "".join(set(original_str))  # 集合转字符串,需用join方法
print(unique_str)  # 输出:abc(顺序可能变化,因为集合无序)

4.3 集合的增删改查(基础操作)

集合是可变容器,支持添加、删除元素,但由于无序,无法通过索引修改元素(无索引),查询主要是判断元素是否存在。

(1)增:添加元素(2种常用方法)
s = {1, 2, 3, 4}

# 方法1:add(x):添加单个元素,重复元素不添加(无报错)
s.add(5)
print(s)  # 输出:{1, 2, 3, 4, 5}
s.add(4)  # 添加重复元素,无变化
print(s)  # 输出:{1, 2, 3, 4, 5}

# 方法2:update(iterable):批量添加元素(可迭代对象),重复元素自动过滤
s.update([5, 6, 7])  # 添加列表中的元素
print(s)  # 输出:{1, 2, 3, 4, 5, 6, 7}
s.update(("a", "b"))  # 添加元组中的元素
print(s)  # 输出:{1, 2, 3, 4, 5, 6, 7, 'a', 'b'}
(2)删:删除元素(4种常用方法)
s = {1, 2, 3, 4, 5, 6}

# 方法1:remove(x):删除指定元素,元素不存在报错
s.remove(3)
print(s)  # 输出:{1, 2, 4, 5, 6}
# s.remove(10)  # 报错:KeyError(10不存在)

# 方法2:discard(x):删除指定元素,元素不存在不报错(更安全)
s.discard(4)
print(s)  # 输出:{1, 2, 5, 6}
s.discard(10)  # 元素不存在,无变化,不报错

# 方法3:pop():删除任意一个元素(集合无序),返回被删除的元素,空集合报错
deleted_num = s.pop()
print(deleted_num)  # 输出:1(随机删除,每次可能不同)
print(s)  # 输出:{2, 5, 6}

# 方法4:clear():清空集合所有元素,保留集合对象
s.clear()
print(s)  # 输出:set()
(3)查:判断元素是否存在(in / not in,最常用)
s = {1, 2, 3, 4, 5}

# 判断元素是否存在,返回布尔值
print(3 in s)  # 输出:True(存在)
print(6 not in s)  # 输出:True(不存在)

# 集合无索引,无法通过索引访问元素(报错)
# print(s[0])  # 报错:TypeError

4.4 集合的核心:集合运算(重点,实用场景)

集合支持交集、并集、差集、对称差集等运算,适合用于两个集合之间的对比(如找出共同元素、不同元素),可通过运算符或方法实现。

# 定义两个集合
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}

# 1. 并集:两个集合的所有元素(去重),运算符 | 或方法 union()
print(a | b)  # 输出:{1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b))  # 输出同上

# 2. 交集:两个集合的共同元素,运算符 & 或方法 intersection()
print(a & b)  # 输出:{4, 5}
print(a.intersection(b))  # 输出同上

# 3. 差集:a中有、b中没有的元素,运算符 - 或方法 difference()
print(a - b)  # 输出:{1, 2, 3}
print(a.difference(b))  # 输出同上

# 4. 对称差集:两个集合中互不相同的元素(并集 - 交集),运算符 ^ 或方法 symmetric_difference()
print(a ^ b)  # 输出:{1, 2, 3, 6, 7, 8}
print(a.symmetric_difference(b))  # 输出同上

# 5. 子集/超集判断:issubset() / issuperset()
c = {1, 2}
print(c.issubset(a))  # 输出:True(c是a的子集)
print(a.issuperset(c))  # 输出:True(a是c的超集)

5 字符串高级操作(衔接基础,重点拓展)

在第二阶段,我们学习了字符串的基础用法(创建、拼接、基本输入输出),本次第四阶段,我们重点拓展字符串的高级操作——切片、格式化、常用内置方法,这些操作在日常编程中高频使用,结合容器类型,能实现更灵活的文本处理。

5.1 字符串切片(与列表、元组切片一致)

字符串是有序的字符序列,支持切片操作,语法与列表、元组完全一致:字符串[起始索引:结束索引:步长],核心规则:左闭右开,支持正向、反向切片,可快速获取子字符串。

s = "Hello, Python!"

# 1. 基础切片
print(s[0:5])  # 输出:Hello(从0到4,左闭右开)
print(s[7:])   # 输出:Python!(从7到末尾)
print(s[:5])   # 输出:Hello(从开头到4)
print(s[:])    # 输出:Hello, Python!(复制整个字符串)

# 2. 指定步长切片
print(s[0:12:2])  # 输出:Hlo yhn(步长为2,间隔1个字符)
print(s[::-1])    # 输出:!nohtyP ,olleH(步长为-1,反转字符串)

# 3. 反向切片
print(s[-7:-1])  # 输出:Python(从倒数7到倒数1,不包含倒数1)

5.2 字符串格式化(3种常用方式,重点掌握)

字符串格式化用于将变量、数字等插入到字符串中,实现动态文本生成(如拼接用户信息、输出结果),常用3种方式,重点掌握f-string(最简洁、最高效)。

name = "张三"
age = 18
score = 95.5

# 方式1:f-string(Python3.6+,最常用,简洁高效)
# 语法:f"字符串{变量/表达式}",可直接嵌入变量和表达式
print(f"我的名字是{name},年龄是{age}岁,成绩是{score}分")
# 格式化数字(保留2位小数)
print(f"我的成绩是{score:.2f}分")  # 输出:我的成绩是95.50分
# 嵌入表达式
print(f"明年我{age+1}岁")  # 输出:明年我19岁

# 方式2:format()方法(兼容性好,适用于所有Python3版本)
print("我的名字是{},年龄是{}岁,成绩是{}分".format(name, age, score))
# 指定占位符顺序(避免参数顺序错误)
print("我的名字是{0},年龄是{1}岁,{0}的成绩是{2}分".format(name, age, score))

# 方式3:%占位符(老式方法,兼容性强,较少使用)
print("我的名字是%s,年龄是%d岁,成绩是%f分" % (name, age, score))
# 格式化数字(保留2位小数)
print("我的成绩是%.2f分" % score)  # 输出:我的成绩是95.50分

推荐优先级:f-string > format()方法 > %占位符,日常编程优先使用f-string,简洁又高效。

5.3 字符串常用内置方法(高频使用,必记)

字符串是不可变类型(与元组一致),所有修改类方法都会返回新字符串,不会修改原字符串,重点记以下高频方法:

s = "  Hello, Python!  "

# 1. 去除空格(最常用)
print(s.strip())  # 输出:Hello, Python!(去除前后两端空格,保留中间)
print(s.lstrip()) # 输出:Hello, Python!  (去除左端空格)
print(s.rstrip()) # 输出:  Hello, Python!(去除右端空格)

# 2. 大小写转换
print(s.upper())  # 输出:  HELLO, PYTHON!  (全部大写)
print(s.lower())  # 输出:  hello, python!  (全部小写)
print(s.title())  # 输出:  Hello, Python!  (每个单词首字母大写)

# 3. 查找与替换
# find(x):查找子字符串x的索引,不存在返回-1(不报错)
print(s.find("Python"))  # 输出:8(Python的起始索引)
print(s.find("Java"))    # 输出:-1(不存在)
# replace(old, new):将子字符串old替换为new,可指定替换次数
print(s.replace("Python", "Java"))  # 输出:  Hello, Java!  (全部替换)
print(s.replace("o", "0", 1))       # 输出:  Hell0, Python!  (替换1次)

# 4. 分割与拼接
# split(sep):按指定分隔符sep分割字符串,返回列表
s1 = "a,b,c,d"
print(s1.split(","))  # 输出:['a', 'b', 'c', 'd'](按逗号分割)
# join(iterable):将可迭代对象(如列表)的元素拼接为字符串,分隔符为原字符串
list1 = ["Hello", "Python"]
print(" ".join(list1))  # 输出:Hello Python(用空格拼接)

# 5. 判断字符串类型
s2 = "12345"
s3 = "abc123"
print(s2.isdigit())  # 输出:True(判断是否全是数字)
print(s3.isalpha())  # 输出:False(判断是否全是字母)
print(s3.isalnum())  # 输出:True(判断是否全是字母+数字)

# 6. 补充:长度、计数
print(len(s))  # 输出:16(字符串长度,包含空格)
print(s.count("o"))  # 输出:2(统计o出现的次数)

6 总结

到这里,Python3基础学习第四阶段「容器数据类型」的核心内容就全部梳理完毕了!这一阶段的知识点是Python数据处理的“核心工具”,我们学习了四种核心容器和字符串高级操作,它们各自有明确的适用场景,串联起来就能高效处理各种数据场景:

  • 列表(List):有序、可变,适合存储需要动态修改的有序数据(如待办事项、数据列表);
  • 元组(Tuple):有序、不可变,适合存储固定不变的数据(如坐标、配置参数),安全性高;
  • 字典(Dictionary):键值对、可变,适合存储关联数据(如用户信息、配置项),查询效率高;
  • 集合(Set):无序、唯一,适合去重、集合运算(如找出共同元素),查询效率高;
  • 字符串高级操作:切片、格式化、内置方法,适合文本处理(如拼接、替换、去空格)。

对于新手来说,这一阶段的重点不是死记硬背所有方法,而是:理解每种容器的核心特性(可变/不可变、有序/无序、存储方式),记住它们的适用场景——什么时候用列表、什么时候用字典、什么时候用集合,比记住所有方法更重要;其次,多动手敲写代码示例,每一个方法、每一种操作都亲自运行一遍,感受不同容器的使用差异,遇到报错(如索引越界、键不存在)不要慌,结合前面的避坑技巧排查问题,这是掌握容器类型的关键;最后,尝试结合第三阶段的流程控制知识,用容器存储数据、处理数据(如用列表配合循环遍历、用字典存储用户信息并查询),实现简单的小案例,这样才能真正吃透这些“数据仓库”,为后续的学习打下扎实的基础。


转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人
持续创作很不容易,作者将以尽可能的详细把所学知识分享各位开发者,一起进步一起学习。转载请携带链接,转载到微信公众号请勿选择原创,谢谢!
👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍
谢谢支持!