Python 容器数据类型完全指南:从入门到精通,一文搞定列表、元组、字典、集合!
掌握Python核心数据结构,让代码效率翻倍
大家好,我是专注于Python技术的资深开发者。今天我们来深入探讨Python中最重要的知识点之一——容器数据类型。无论你是刚入门的新手,还是想要巩固基础的老手,这篇文章都能帮你彻底理解Python的四大核心容器:列表、元组、字典、集合。
一、什么是序列?
在Python中,序列是一种基本且核心的数据结构,它以有序的方式存储和操作数据。序列中的每个元素都有一个索引位置,我们可以通过索引来访问和修改这些元素。
Python中常见的序列类型包括:列表(List)、元组(Tuple)和字符串(String)。
序列的通用操作
所有序列类型都支持以下操作:
python
# 索引 - 通过位置获取元素 sequence[0] # 获取第一个元素 sequence[-1] # 获取最后一个元素 # 切片 - 获取子序列 sequence[1:3] # 获取索引1到2的元素 sequence[:3] # 获取前3个元素 sequence[2:] # 获取索引2之后的所有元素 sequence[::-1] # 反转序列 # 相加 - 合并两个序列 sequence1 + sequence2 # 乘法 - 重复序列 sequence * 3 # 成员检查 x in sequence # 检查x是否在序列中 # 内置函数 len(sequence) # 长度 max(sequence) # 最大值 min(sequence) # 最小值
二、列表(List):最灵活的容器
列表是Python中使用最广泛的数据结构,它可变、有序,可以存储任意类型的元素。
2.1 创建列表
python
# 基本创建方式 list1 = [100, 200, 300, 400, 500] list2 = [] # 空列表 list3 = list() # 使用构造器创建空列表 # 列表可以包含不同类型的元素 mixed_list = [1, "hello", 3.14, True]
2.2 列表的索引机制
列表中的每个元素都有对应的索引,支持正向索引(从0开始)和负向索引(从-1开始):
text
索引: 0 1 2 3 4 列表: [100, 200, 300, 400, 500] 负索引: -5 -4 -3 -2 -1
2.3 访问与切片
python
list1 = [100, 200, 300, 400, 500] # 索引访问 print(list1[1]) # 输出: 200 print(list1[-2]) # 输出: 400 # 切片操作 print(list1[:]) # [100, 200, 300, 400, 500] - 复制整个列表 print(list1[2:4]) # [300, 400] - 索引2到3(不包含4) print(list1[2:]) # [300, 400, 500] - 索引2到末尾 print(list1[:-2]) # [100, 200, 300] - 开头到索引-2(不包含) print(list1[2:-1]) # [300, 400] - 索引2到-1(不包含) print(list1[::-1]) # [500, 400, 300, 200, 100] - 倒序
2.4 添加元素
python
list1 = [100, 200, 300, 400, 500] # append() - 在末尾添加 list1.append(600) print(list1) # [100, 200, 300, 400, 500, 600] # insert() - 在指定位置插入 list1.insert(2, 700) # 在索引2的位置插入700 print(list1) # [100, 200, 700, 300, 400, 500, 600] # extend() - 扩展列表 list2 = [1, 2, 3] list1.extend(list2) # 将list2的元素追加到list1末尾 print(list1) # [100, 200, 700, 300, 400, 500, 600, 1, 2, 3]
2.5 修改元素
python
list1 = [100, 200, 300, 400, 500] # 通过下标修改 list1[0] = -1 print(list1) # [-1, 200, 300, 400, 500] # 通过切片修改 list1[2:4] = ["a", "b", "c"] print(list1) # [-1, 200, 'a', 'b', 'c', 500]
2.6 删除元素
python
list1 = [100, 200, 300, 400, 500] # del - 删除指定位置 del list1[2] print(list1) # [100, 200, 400, 500] # remove() - 删除第一次出现的指定值 list1.remove(200) print(list1) # [100, 400, 500] # pop() - 弹出指定位置元素(默认弹出最后一个) popped = list1.pop() print(popped) # 500 print(list1) # [100, 400] # clear() - 清空列表 list1.clear() print(list1) # []
2.7 列表遍历
python
list1 = [100, 200, 300, 400, 500]
# 方式1:直接遍历元素
for i in list1:
print(i)
# 方式2:通过索引遍历
for i in range(len(list1)):
print(i, list1[i])
# 方式3:使用enumerate()同时获取索引和值
for i, val in enumerate(list1):
print(i, val)
2.8 列表推导式
列表推导式是Python中最优雅的特性之一,它让你用一行代码就能创建复杂的列表:
python
# 基础列表推导式 - 生成0-4的平方 squares = [x**2 for x in range(5)] print(squares) # [0, 1, 4, 9, 16] # 带条件的列表推导式 - 只取偶数的平方 even_squares = [x**2 for x in range(10) if x % 2 == 0] print(even_squares) # [0, 4, 16, 36, 64] # 使用现有列表 list1 = [1, 2, 3, 4, 5] squares2 = [x**2 for x in list1] print(squares2) # [1, 4, 9, 16, 25] # 多重循环 - 生成笛卡尔积 list1 = [1, 2, 3] list2 = ["a", "b", "c"] pairs = [(i, j) for i in list1 for j in list2] print(pairs) # [(1,'a'), (1,'b'), (1,'c'), (2,'a'), ...]
2.9 zip()函数
zip()函数可以将多个可迭代对象中对应位置的元素打包成元组:
python
list1 = [1, 2, 3, 4, 5] list2 = ["a", "b", "c", "d", "e"] zipped = zip(list1, list2) print(list(zipped)) # [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')] # 如果长度不同,zip()会以最短的为准 list3 = [1, 2, 3] list4 = ["a", "b", "c", "d", "e"] print(list(zip(list3, list4))) # [(1, 'a'), (2, 'b'), (3, 'c')]
2.10 列表的常用函数汇总
| 函数 | 说明 |
|---|---|
list.append(x) |
在列表末尾追加x |
list.insert(index,x) |
在指定位置插入x |
list.extend(iterable) |
将可迭代对象的所有元素追加到列表末尾 |
list.remove(x) |
删除第一次出现的x |
list.pop([index]) |
删除指定位置的数据,默认为末尾数据 |
list.clear() |
清空列表中元素 |
list.index(x[,start[,end]]) |
返回x在列表中首次出现的位置 |
list.count(x) |
返回x的数量 |
list.sort([reverse=True]) |
对列表就地排序 |
list.reverse() |
反转列表中的元素 |
list.copy() |
拷贝列表 |
三、字符串(String):不可变的文本序列
字符串是Python中最常用的数据类型之一,它不可变、有序,用于存储文本数据。
3.1 字符串的特性
python
# 创建字符串
str1 = "hello world"
str2 = 'Python is great'
str3 = """多行
字符串"""
# 索引和切片
print(str1[0]) # h
print(str1[-1]) # d
print(str1[4:-3]) # o w
# 字符串拼接
str1 = "hello"
str2 = "world"
print(str1 + " " + str2) # hello world
# 字符串重复
print("ha" * 3) # hahaha
# 成员检查
print("lo" in "hello") # True
3.2 原始字符串
当字符串中包含大量转义字符时,可以使用原始字符串(在引号前加r或R):
python
# 普通字符串:\n会被解析为换行
print("hello\nworld")
# 输出:
# hello
# world
# 原始字符串:所有字符按字面意思处理
print(r"hello\nworld")
# 输出: hello\nworld
3.3 字符串常用方法
python
# 大小写转换
text = "Hello World"
print(text.upper()) # HELLO WORLD
print(text.lower()) # hello world
print(text.swapcase()) # hELLO wORLD
print(text.capitalize()) # Hello world
print(text.title()) # Hello World
# 查找与替换
text = "hello world, hello python"
print(text.find("world")) # 6 - 返回第一次出现的位置
print(text.replace("hello", "hi")) # hi world, hi python
# 分割与连接
words = text.split() # 默认按空白分割
print(words) # ['hello', 'world,', 'hello', 'python']
joined = " ".join(words) # 用空格连接
print(joined) # hello world, hello python
# 去除空白
text = " hello "
print(text.strip()) # "hello" - 去除两端空白
print(text.lstrip()) # "hello " - 去除左侧空白
print(text.rstrip()) # " hello" - 去除右侧空白
# 检查开头/结尾
filename = "document.pdf"
print(filename.startswith("doc")) # True
print(filename.endswith(".pdf")) # True
3.4 字符串格式化
python
# f-string(Python 3.6+)
name = "Alice"
age = 18
print(f"{name} is {age} years old")
# format()方法
print("{} is {} years old".format(name, age))
# %格式化(传统方式)
print("%s is %d years old" % (name, age))
四、元组(Tuple):不可变的序列
元组与列表非常相似,但一旦创建就不能修改。这种不可变性让元组在某些场景下更安全、更高效。
4.1 创建元组
python
# 基本创建 tuple1 = (100, 200, 300, 400, 500) tuple2 = () # 空元组 tuple3 = tuple() # 使用构造器 # 特别注意:单元素元组需要加逗号 tuple4 = (100,) # 正确:这是一个元组 not_tuple = (100) # 错误:这是一个整数 # 元组推导式返回的是生成器 tuple_generator = (x for x in range(5)) print(type(tuple_generator)) # <class 'generator'> tuple5 = tuple(tuple_generator) # 转换为元组 print(tuple5) # (0, 1, 2, 3, 4)
4.2 元组的操作
元组支持的操作与列表类似,但由于不可变性,没有添加、修改、删除元素的方法:
python
tuple1 = (100, 200, 300, 400, 500)
# 索引和切片
print(tuple1[2]) # 300
print(tuple1[-1]) # 500
print(tuple1[2:4]) # (300, 400)
# 拼接和重复
tuple2 = ("a", "b", "c")
print(tuple1 + tuple2) # (100, 200, 300, 400, 500, 'a', 'b', 'c')
print(tuple1 * 2) # (100, 200, 300, 400, 500, 100, 200, 300, 400, 500)
# 成员检查
print(300 in tuple1) # True
# 内置函数
print(len(tuple1)) # 5
print(max(tuple1)) # 500
print(min(tuple1)) # 100
print(sum(tuple1)) # 1500
4.3 元组的"可变"陷阱
元组的不可变性是指元组对象本身不可变,但如果元组包含可变对象(如列表),这些可变对象的内容是可以修改的:
python
tuple1 = (100, 200, 300, [1, 2, 3]) print(id(tuple1)) # 查看内存地址 # 修改元组中的列表 tuple1[3].append(4) print(tuple1) # (100, 200, 300, [1, 2, 3, 4]) print(id(tuple1)) # 内存地址不变 # 但尝试修改元组的元素会报错 # tuple1[0] = 999 # TypeError: 'tuple' object does not support item assignment
4.4 元组的实际应用
python
# 1. 函数返回多个值
def get_user_info():
name = "Alice"
age = 18
city = "Beijing"
return name, age, city # 实际返回的是元组
info = get_user_info()
print(info) # ('Alice', 18, 'Beijing')
name, age, city = get_user_info() # 解包
print(name) # Alice
# 2. 作为字典的键(列表不能作为字典键)
locations = {}
locations[("Beijing", "China")] = "Capital" # 元组作为键
# 3. 保护数据不被修改
COORDINATES = (39.9042, 116.4074) # 坐标常量
五、集合(Set):无序的不重复元素集
集合是一个无序、元素唯一的数据结构,非常适合去重和集合运算。
5.1 创建集合
python
# 使用花括号
set1 = {1, 2, 3, 4, 5}
# 使用set()函数
set2 = set([1, 2, 3, 3, 4, 5]) # 自动去重,结果: {1, 2, 3, 4, 5}
set3 = set("hello") # 字符串转换为集合,结果: {'h', 'e', 'l', 'o'}
# 空集合必须用set(),{}是空字典
empty_set = set()
empty_dict = {}
# 集合推导式
set4 = {x for x in range(10) if x % 2 == 0}
print(set4) # {0, 2, 4, 6, 8}
5.2 集合的基本操作
python
# 添加元素
set1 = {1, 2, 3}
set1.add(4)
print(set1) # {1, 2, 3, 4}
# update() - 添加多个元素
set1.update([5, 6, 7])
print(set1) # {1, 2, 3, 4, 5, 6, 7}
# 删除元素
set1.remove(4) # 元素不存在时抛出KeyError
set1.discard(10) # 元素不存在时什么也不做
print(set1.pop()) # 随机弹出并返回一个元素
set1.clear() # 清空集合
5.3 集合运算
集合支持数学上的集合运算,非常直观:
python
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
# 并集(union)
print(A | B) # {1, 2, 3, 4, 5, 6, 7, 8}
print(A.union(B)) # 同上
# 交集(intersection)
print(A & B) # {4, 5}
print(A.intersection(B)) # 同上
# 差集(difference)
print(A - B) # {1, 2, 3} - 在A中但不在B中
print(B - A) # {6, 7, 8} - 在B中但不在A中
# 对称差集(symmetric difference)
print(A ^ B) # {1, 2, 3, 6, 7, 8} - 不在交集中的所有元素
print(A.symmetric_difference(B)) # 同上
# 子集判断
C = {1, 2}
print(C <= A) # True - C是A的子集
print(A >= C) # True - A是C的超集
print(A.isdisjoint(B)) # False - 有交集
5.4 集合的实用场景
python
# 1. 列表去重
list_with_duplicates = [1, 2, 2, 3, 3, 3, 4, 5, 5]
unique_list = list(set(list_with_duplicates))
print(unique_list) # [1, 2, 3, 4, 5]
# 2. 快速成员检查
valid_ids = {1001, 1002, 1003, 1004, 1005}
if 1003 in valid_ids: # O(1)时间复杂度,比列表快得多
print("ID有效")
# 3. 找出两个列表的共同元素
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
common = set(list1) & set(list2)
print(common) # {4, 5}
六、字典(Dictionary):键值对的映射
字典是Python中实现键值对映射的数据结构,键唯一且不可变,值可以是任意类型。
6.1 创建字典
python
# 使用花括号
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
# 使用dict()构造器
dict2 = dict(name="Bob", age=20, gender="female")
dict3 = dict([("name", "Tom"), ("age", 22), ("gender", "male")])
# 空字典
empty_dict1 = {}
empty_dict2 = dict()
# 字典推导式
squares = {x: x**2 for x in range(5)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
6.2 访问和修改
python
dict1 = {"name": "Alice", "age": 18, "gender": "male"}
# 通过键访问
print(dict1["name"]) # Alice
# print(dict1["address"]) # 键不存在时抛出KeyError
# get()方法 - 更安全
print(dict1.get("name")) # Alice
print(dict1.get("address")) # None
print(dict1.get("address", "earth")) # earth - 指定默认值
# 添加/修改元素
dict1["address"] = "earth" # 键不存在则添加
dict1["age"] = 19 # 键存在则修改
print(dict1) # {'name': 'Alice', 'age': 19, 'gender': 'male', 'address': 'earth'}
# update() - 批量更新
dict1.update({"city": "Beijing", "age": 20})
print(dict1) # 更新age,添加city
6.3 删除元素
python
my_dict = {'Name': 'Tom', 'Age': 17, 'City': 'Beijing'}
# del - 删除指定键
del my_dict['Age']
print(my_dict) # {'Name': 'Tom', 'City': 'Beijing'}
# pop() - 弹出并返回值
name = my_dict.pop('Name')
print(name) # Tom
print(my_dict) # {'City': 'Beijing'}
# popitem() - 弹出最后插入的键值对(Python 3.7+)
my_dict['Age'] = 17
my_dict['Gender'] = 'male'
last_item = my_dict.popitem()
print(last_item) # ('Gender', 'male')
print(my_dict) # {'City': 'Beijing', 'Age': 17}
# clear() - 清空
my_dict.clear()
print(my_dict) # {}
6.4 字典遍历
python
my_dict = {"name": "Alice", "age": 18, "city": "Beijing"}
# 遍历所有键
for key in my_dict.keys():
print(key)
# 遍历所有值
for value in my_dict.values():
print(value)
# 遍历键值对
for key, value in my_dict.items():
print(f"{key}: {value}")
# 检查键是否存在
if "name" in my_dict:
print("name exists")
6.5 字典的常用方法
| 方法 | 说明 |
|---|---|
dict.keys() |
返回所有键的视图对象 |
dict.values() |
返回所有值的视图对象 |
dict.items() |
返回所有键值对的视图对象 |
dict.get(key[,default]) |
安全获取值,可设默认值 |
dict.setdefault(key[,default]) |
获取值,键不存在则设置默认值 |
dict.update(other) |
用其他字典更新当前字典 |
dict.pop(key[,default]) |
弹出指定键的值 |
dict.popitem() |
弹出最后插入的键值对 |
dict.clear() |
清空字典 |
dict.copy() |
浅拷贝字典 |
七、四大容器的对比与选择
| 数据结构 | 是否可变 | 是否允许重复 | 是否有序 | 定义符号 | 适用场景 |
|---|---|---|---|---|---|
| 列表 | 可变 | 允许 | 有序 | []或list() |
存储有序数据,需要频繁增删改查 |
| 元组 | 不可变 | 允许 | 有序 | ()或tuple() |
存储不变的数据,作为字典键 |
| 字典 | 可变 | 键不允许,值允许 | 键有序* | {}或dict() |
键值对映射,快速查找 |
| 集合 | 可变 | 不允许 | 无序 | {}或set() |
去重、成员检查、集合运算 |
*注:Python 3.7+版本中,字典保持插入顺序;Python 3.6中作为实现细节,3.7后成为语言特性。
如何选择合适的数据结构?
-
需要保持顺序? → 选择列表或元组
-
需要修改数据? → 选择列表、字典或集合(元组不可变)
-
需要快速查找? → 选择字典或集合(哈希表,O(1)时间复杂度)
-
需要去除重复? → 选择集合
-
需要键值映射? → 选择字典
-
数据需要作为字典键? → 选择元组(不可变类型)
-
需要存储同类型数据且需要排序? → 选择列表
八、高级技巧与最佳实践
8.1 列表 vs 元组性能
元组通常比列表更高效,因为不可变性允许Python进行优化:
python
import sys list_obj = [1, 2, 3, 4, 5] tuple_obj = (1, 2, 3, 4, 5) print(sys.getsizeof(list_obj)) # 约 56 字节 print(sys.getsizeof(tuple_obj)) # 约 48 字节
8.2 深拷贝与浅拷贝
python
import copy original = [[1, 2, 3], [4, 5, 6]] # 浅拷贝 - 只复制外层,内层列表仍是引用 shallow = original.copy() shallow[0][0] = 999 print(original) # [[999, 2, 3], [4, 5, 6]] - 原数据被修改 # 深拷贝 - 完全复制所有层级 original = [[1, 2, 3], [4, 5, 6]] deep = copy.deepcopy(original) deep[0][0] = 999 print(original) # [[1, 2, 3], [4, 5, 6]] - 原数据不变
8.3 字典的默认值处理
python
from collections import defaultdict
# 传统方式
my_dict = {}
if 'count' not in my_dict:
my_dict['count'] = 0
my_dict['count'] += 1
# 使用setdefault
my_dict.setdefault('count', 0)
my_dict['count'] += 1
# 使用defaultdict
my_dict = defaultdict(int)
my_dict['count'] += 1 # 自动初始化为0
8.4 列表推导式 vs map/filter
python
# 列表推导式(Pythonic) squares = [x**2 for x in range(10) if x % 2 == 0] # 传统map/filter squares = list(map(lambda x: x**2, filter(lambda x: x % 2 == 0, range(10)))) # 列表推导式更简洁易读
总结
Python的容器数据类型是编程的基础,熟练掌握它们能让你的代码更加优雅高效:
-
列表是最灵活的容器,适合需要频繁修改的有序数据
-
元组是不可变的安全选择,适合保护数据不被意外修改
-
字典提供了最快的键值查找,适合映射关系
-
集合擅长去重和数学集合运算
在实际开发中,选择合适的数据结构能显著提升代码性能和可读性。建议根据数据的特性和操作需求来选择:
-
需要顺序、允许重复 → 列表
-
需要顺序、不允许修改 → 元组
-
需要快速查找、键值映射 → 字典
-
需要去重、集合运算 → 集合
希望这篇文章能帮助你彻底掌握Python的容器数据类型。如果觉得有用,欢迎点赞收藏,也欢迎在评论区留言讨论!
*本文内容基于Python 3.10+版本,不同版本间可能有细微差异。*
更多推荐



所有评论(0)