Python 数据容器

Python数据容器总结与对比

📊 数据容器概览

容器类型有序性可变性重复元素使用场景
列表(list)有序可变允许通用序列,存储同类型数据
元组(tuple)有序不可变允许固定数据集合,字典键
字典(dict)有序(Python3.7+)可变键不允许重复键值对映射
集合(set)无序可变不允许去重,集合运算
字符串(str)有序不可变允许文本处理

📋 列表(List)

基本操作示例

# 创建
numbers = [1, 2, 3, 4, 5]
fruits = ['apple', 'banana', 'cherry']
mixed = [1, 'hello', 3.14, True]

# 访问元素
print(fruits[0]) # 'apple'
print(fruits[-1]) # 'cherry' (倒数第一个)
print(fruits[1:3]) # ['banana', 'cherry'] (切片)

# 修改
fruits[1] = 'blueberry' # 修改元素
fruits.append('orange') # 添加元素
fruits.insert(1, 'mango') # 插入元素
fruits.extend(['grape', 'kiwi']) # 扩展列表

# 删除
removed = fruits.pop() # 删除并返回最后一个元素
removed2 = fruits.pop(1) # 删除指定位置元素
fruits.remove('apple') # 删除指定值
del fruits[0] # 删除指定位置

# 常用方法
fruits.sort() # 排序
fruits.reverse() # 反转
count = fruits.count('apple') # 计数
index = fruits.index('banana') # 查找索引
fruits_copy = fruits.copy() # 浅拷贝

# 列表推导式
squares = [x**2 for x in range(10)]
even_squares = [x**2 for x in range(10) if x % 2 == 0]

🏷️ 元组(Tuple)

基本操作示例

# 创建
coordinates = (10, 20)
colors = ('red', 'green', 'blue')
single_element = (42,) # 注意逗号,否则不是元组
mixed = (1, 'hello', [1, 2, 3]) # 元组可以包含可变元素

# 访问元素
print(colors[0]) # 'red'
print(colors[-1]) # 'blue'
print(colors[1:]) # ('green', 'blue')

# 元组不可变,但可以重新赋值
colors = ('red', 'green', 'blue', 'yellow') # 重新赋值

# 解包
x, y = coordinates # x=10, y=20
first, *rest = colors # first='red', rest=['green', 'blue']

# 常用方法
count = colors.count('red') # 计数
index = colors.index('blue') # 查找索引

# 元组比列表更节省内存,访问更快
import sys
list_size = sys.getsizeof([1, 2, 3])
tuple_size = sys.getsizeof((1, 2, 3))
print(f"List size: {list_size}, Tuple size: {tuple_size}")

📚 字典(Dict)

基本操作示例

# 创建
person = {'name': 'Alice', 'age': 30, 'city': 'New York'}
grades = dict(math=90, science=85, history=88)
empty_dict = {}

# 访问元素
print(person['name']) # 'Alice'
print(person.get('age', 0)) # 30,如果不存在返回默认值0

# 添加/修改
person['email'] = 'alice@example.com' # 添加
person['age'] = 31 # 修改

# 删除
del person['city'] # 删除键值对
email = person.pop('email') # 删除并返回值
person.clear() # 清空字典

# 常用方法
keys = person.keys() # 所有键
values = person.values() # 所有值
items = person.items() # 所有键值对

# 遍历
for key in person:
print(key, person[key])

for key, value in person.items():
print(f"{key}: {value}")

# 字典推导式
squares = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 合并字典 (Python 3.9+)
dict1 = {'a': 1, 'b': 2}
dict2 = {'b': 3, 'c': 4}
merged = dict1 | dict2 # {'a': 1, 'b': 3, 'c': 4}

🎯 集合(Set)

基本操作示例

# 创建
fruits = {'apple', 'banana', 'cherry'}
numbers = set([1, 2, 3, 4, 5])
empty_set = set() # 注意:{}创建的是空字典

# 添加/删除元素
fruits.add('orange')
fruits.update(['grape', 'kiwi']) # 添加多个
fruits.remove('banana') # 删除,不存在则报错
fruits.discard('mango') # 删除,不存在不报错
popped = fruits.pop() # 随机删除一个元素并返回

# 集合运算
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}

union = set1 | set2 # 并集: {1, 2, 3, 4, 5, 6}
intersection = set1 & set2 # 交集: {3, 4}
difference = set1 - set2 # 差集: {1, 2}
symmetric_diff = set1 ^ set2 # 对称差集: {1, 2, 5, 6}

# 集合关系
is_subset = {1, 2}.issubset({1, 2, 3}) # True
is_superset = {1, 2, 3}.issuperset({1, 2}) # True
is_disjoint = {1, 2}.isdisjoint({3, 4}) # True

# 集合推导式
even_squares = {x**2 for x in range(10) if x % 2 == 0}

📝 字符串(String)

基本操作示例

# 创建
text = "Hello, World!"
multiline = """这是一个
多行字符串"""

# 访问和切片
print(text[0]) # 'H'
print(text[-1]) # '!'
print(text[0:5]) # 'Hello'
print(text[::2]) # 'Hlo ol!' (步长为2)

# 常用方法
text.lower() # 转为小写
text.upper() # 转为大写
text.strip() # 去除两端空格
text.split(',') # 分割字符串
','.join(['a', 'b']) # 连接字符串: 'a,b'
text.replace('World', 'Python') # 替换
text.find('World') # 查找子串位置
text.startswith('Hello') # 检查开头
text.endswith('!') # 检查结尾

# 格式化
name = "Alice"
age = 30
f"Name: {name}, Age: {age}" # f-string (Python 3.6+)
"Name: {}, Age: {}".format(name, age) # format方法
"Name: %s, Age: %d" % (name, age) # %格式化

# 字符串检查
text.isalpha() # 是否全字母
text.isdigit() # 是否全数字
text.isalnum() # 是否字母或数字
text.isspace() # 是否全空白字符

🔄 容器转换

# 列表 ↔ 元组
my_list = [1, 2, 3]
my_tuple = tuple(my_list) # (1, 2, 3)
new_list = list(my_tuple) # [1, 2, 3]

# 列表 ↔ 集合 (去重)
my_list = [1, 2, 2, 3, 3, 3]
my_set = set(my_list) # {1, 2, 3}
new_list = list(my_set) # [1, 2, 3]

# 字典 ↔ 列表/元组
person = {'name': 'Alice', 'age': 30}
keys = list(person.keys()) # ['name', 'age']
values = tuple(person.values()) # ('Alice', 30)
items = list(person.items()) # [('name', 'Alice'), ('age', 30)]

# 字符串 ↔ 列表
text = "apple,banana,cherry"
fruits = text.split(',') # ['apple', 'banana', 'cherry']
new_text = '-'.join(fruits) # 'apple-banana-cherry'

⚡ 性能对比

import timeit

# 查找速度对比
list_test = list(range(1000000))
set_test = set(range(1000000))

# 列表查找(O(n))
list_time = timeit.timeit('999999 in list_test', globals=globals(), number=1000)
# 集合查找(O(1))
set_time = timeit.timeit('999999 in set_test', globals=globals(), number=1000)

print(f"列表查找: {list_time:.4f}秒")
print(f"集合查找: {set_time:.4f}秒")

🎯 选择指南

  1. 需要有序、可重复、可变序列 → 使用 列表
  2. 需要有序、可重复、不可变序列 → 使用 元组
  3. 需要键值对映射 → 使用 字典
  4. 需要去重或集合运算 → 使用 集合
  5. 处理文本数据 → 使用 字符串
  6. 需要哈希化(作为字典键) → 使用 元组(不可变类型)

📦 特殊容器(collections模块)

from collections import deque, Counter, defaultdict, OrderedDict, namedtuple

# 双端队列
dq = deque([1, 2, 3])
dq.appendleft(0) # 左侧添加
dq.popleft() # 左侧弹出

# 计数器
counter = Counter(['apple', 'banana', 'apple', 'cherry'])
print(counter) # Counter({'apple': 2, 'banana': 1, 'cherry': 1})

# 默认字典
dd = defaultdict(int)
dd['key'] += 1 # 自动初始化为0

# 命名元组
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y) # 10 20