数据结构概述
Python提供了多种内置数据结构,其中四种最为核心:列表(List)、元组(Tuple)、字典(Dict)和集合(Set)。它们各有特点,适用于不同的场景。
数据结构 | 特性 | 是否可变 | 是否有序 | 元素要求 |
---|---|---|---|---|
列表(List) | 有序、可重复 | 可变 | 有序 | 任意类型 |
元组(Tuple) | 有序、可重复 | 不可变 | 有序 | 任意类型 |
字典(Dict) | 键值对、键唯一 | 可变 | Python 3.7+有序 | 键必须可哈希 |
集合(Set) | 无序、元素唯一 | 可变 | 无序 | 必须可哈希 |
1. 列表 (List)
特性:有序、可变、可重复元素集合
有序
可变
可重复元素
支持索引和切片
a. 创建列表
# 直接创建
my_list = [1, 2, 3, 'hello', 3.14]
empty_list = []
# 使用 list() 构造函数
from_range = list(range(5)) # [0, 1, 2, 3, 4]
from_string = list("abc") # ['a', 'b', 'c']
from_tuple = list((1, 2, 3)) # [1, 2, 3]
b. 访问元素 (索引和切片)
my_list = ['a', 'b', 'c', 'd', 'e']
print(my_list[0]) # 输出: 'a'
print(my_list[-1]) # 输出: 'e' (最后一个元素)
# print(my_list[10]) # 错误! IndexError: list index out of range
# 切片 (Slicing)
my_list = [0, 1, 2, 3, 4, 5, 6]
print(my_list[1:4]) # [1, 2, 3] (索引1到3)
print(my_list[:3]) # [0, 1, 2] (从开始到索引2)
print(my_list[3:]) # [3, 4, 5, 6] (从索引3到最后)
print(my_list[::2]) # [0, 2, 4, 6] (每隔一个取一个)
print(my_list[::-1]) # [6, 5, 4, 3, 2, 1, 0] (反转列表)
# 切片是创建新列表,不会修改原列表
c. 修改元素
my_list = [1, 2, 3]
# 通过索引修改
my_list[0] = 100 # [100, 2, 3]
# 通过切片修改(可以改变元素数量)
my_list[1:3] = [200, 300] # [100, 200, 300]
my_list[1:3] = [200, 300, 400] # [100, 200, 300, 400] (替换并增加了元素)
my_list[1:4] = [] # [100] (相当于删除了切片部分)
d. 添加元素
my_list = [1, 2]
my_list.append(3) # [1, 2, 3]
my_list.insert(1, 99) # [1, 99, 2, 3] (在索引1处插入99)
my_list.extend([4, 5]) # [1, 99, 2, 3, 4, 5]
# my_list.append([4, 5]) # 错误!这会得到 [1, 2, 3, [4, 5]]
e. 删除元素
my_list = [10, 20, 30, 40, 50, 30]
my_list.remove(30) # 删除第一个30 -> [10, 20, 40, 50, 30]
popped_item = my_list.pop(2) # 删除索引2的元素(40),popped_item = 40 -> [10, 20, 50, 30]
del my_list[0] # 删除索引0 -> [20, 50, 30]
del my_list[1:] # 删除索引1及之后的所有 -> [20]
my_list.clear() # []
f. 查找与信息
my_list = ['a', 'b', 'c', 'a', 'b']
print(my_list.index('b')) # 1
print(my_list.index('b', 2)) # 4 (从索引2开始找)
print(my_list.count('a')) # 2
print(len(my_list)) # 5
print('z' in my_list) # False
g. 排序与反转
nums = [3, 1, 4, 1, 5]
nums.sort() # 原地排序 -> [1, 1, 3, 4, 5]
new_nums = sorted(nums, reverse=True) # 新列表 [5, 4, 3, 1, 1], nums不变
words = ['apple', 'banana', 'cherry', 'date']
words.sort(key=len) # 按字符串长度排序 -> ['date', 'apple', 'banana', 'cherry']? 注意:长度相同时,相对顺序不变
# 更稳定的排序:先按长度,再按字母本身
words.sort(key=lambda x: (len(x), x)) # -> ['date', 'apple', 'banana', 'cherry']
nums.reverse() # 原地反转 -> [5, 4, 3, 1, 1]
rev_iter = reversed(nums) # 获取迭代器
rev_list = list(rev_iter) # 将迭代器转为列表 -> [1, 1, 3, 4, 5]
h. 列表推导式 (List Comprehension)
# 语法:[expression for item in iterable if condition]
squares = [x**2 for x in range(5)] # [0, 1, 4, 9, 16]
evens = [x for x in range(10) if x % 2 == 0] # [0, 2, 4, 6, 8]
2. 元组 (Tuple)
特性:有序、不可变、可重复元素集合
有序
不可变
可重复元素
可哈希
元组的大部分操作与列表类似,但无法修改其内容(增、删、改)。
a. 创建元组
# 直接创建,用逗号分隔,通常用圆括号括起来
my_tuple = (1, 2, 3)
single_item_tuple = (42,) # 注意逗号!(42) 只是一个整数
empty_tuple = ()
# 使用 tuple() 构造函数
my_tuple = tuple([1, 2, 3]) # (1, 2, 3)
b. 访问元素
与列表完全一致,使用索引和切片。切片返回的也是元组。
my_tuple = ('a', 'b', 'c', 'd')
print(my_tuple[1]) # 'b'
print(my_tuple[-1]) # 'd'
print(my_tuple[1:3]) # ('b', 'c')
c. "修改"的替代方案
由于不可变,不能直接修改。但可以通过拼接来创建新元组。
my_tuple = (1, 2, 3)
# my_tuple[0] = 100 # TypeError: 'tuple' object does not support item assignment
new_tuple = my_tuple + (4, 5) # (1, 2, 3, 4, 5)
another_tuple = my_tuple[:2] + (99,) + my_tuple[2:] # (1, 2, 99, 3)
d. 查找与信息
与列表类似,有 index(), count(), len(), in 操作。
my_tuple = ('a', 'b', 'c', 'a')
print(my_tuple.index('c')) # 2
print(my_tuple.count('a')) # 2
print('z' in my_tuple) # False
e. 元组的优势
- 安全性:数据不会被意外修改,用作字典的键或集合的元素。
- 性能:通常比列表创建和遍历更快。
- 可哈希性 (Hashable):因为不可变,所以可哈希,这是作为字典键的关键要求。
3. 字典 (Dict)
特性:无序(Python 3.7+ 开始,插入顺序被保留)、可变、键值对集合
键值对
键必须唯一
键必须可哈希
Python 3.7+有序
a. 创建字典
# 直接创建,花括号 {key: value}
my_dict = {'name': 'Alice', 'age': 30, 'city': 'New York'}
empty_dict = {}
# 使用 dict() 构造函数
my_dict = dict(name='Bob', age=25) # {'name': 'Bob', 'age': 25}
my_dict = dict([('name', 'Charlie'), ('age', 28)]) # 从二元组列表创建
b. 访问与修改元素
my_dict = {'name': 'Alice', 'age': 30}
print(my_dict['name']) # 'Alice'
my_dict['age'] = 31 # 修改已有键的值
my_dict['job'] = 'Engineer' # 添加新的键值对
# print(my_dict['salary']) # KeyError: 'salary'
c. 安全的访问方法
my_dict = {'a': 1}
print(my_dict.get('b', 0)) # 0 (键'b'不存在,返回默认值0)
value = my_dict.setdefault('c', 100)# 键'c'不存在,插入 'c':100,返回100
print(my_dict) # {'a': 1, 'c': 100}
d. 删除元素
my_dict = {'a': 1, 'b': 2, 'c': 3}
val = my_dict.pop('b') # 删除键'b', val = 2, 字典变为 {'a': 1, 'c': 3}
key, val = my_dict.popitem() # 删除最后插入的项 ('c', 3)
del my_dict['a'] # 删除键'a'
my_dict.clear() # {}
e. 遍历字典
my_dict = {'name': 'Alice', 'age': 30}
# 遍历所有键
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}")
f. 字典推导式 (Dict Comprehension)
# 语法:{key_expression: value_expression for item in iterable if condition}
squares = {x: x**2 for x in range(5)} # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
4. 集合 (Set)
特性:无序、可变、元素唯一、不重复
无序
元素唯一
可变的
支持集合运算
主要用于成员测试、去重和数学集合运算。
a. 创建集合
# 直接创建,用花括号{},但不是键值对
my_set = {1, 2, 3, 3} # 自动去重 -> {1, 2, 3}
# empty_set = {} # 错误!这会创建一个空字典
empty_set = set() # 正确创建空集合的方法
# 使用 set() 构造函数,可从任何可迭代对象去重创建
from_list = set([1, 2, 2, 3]) # {1, 2, 3}
from_string = set("hello") # {'h', 'e', 'l', 'o'} (注意无序且去重)
b. 添加和删除元素
my_set = {1, 2, 3}
my_set.add(4) # {1, 2, 3, 4}
my_set.update([3, 4, 5])# {1, 2, 3, 4, 5}
my_set.remove(2) # {1, 3, 4, 5}
my_set.discard(10) # 无错误,集合不变
popped = my_set.pop() # 随机弹出一个元素,如1 -> {3, 4, 5}
c. 集合运算
A = {1, 2, 3}
B = {2, 3, 4}
print(A | B) # {1, 2, 3, 4} (并集)
print(A & B) # {2, 3} (交集)
print(A - B) # {1} (差集)
print(A ^ B) # {1, 4} (对称差集)
print({1, 2} <= A) # True (子集判断)
d. 成员测试与去重
这是集合最核心的用途。
# 成员测试
my_set = {1, 2, 3, 4, 5}
print(3 in my_set) # True,速度极快
# 列表去重
duplicate_list = [1, 2, 2, 3, 3, 3]
unique_list = list(set(duplicate_list)) # [1, 2, 3] (注意顺序可能丢失)
# 如果需要保持顺序
from collections import OrderedDict
unique_ordered_list = list(OrderedDict.fromkeys(duplicate_list)) # [1, 2, 3]
e. 集合推导式 (Set Comprehension)
# 语法:{expression for item in iterable if condition}
squares_set = {x**2 for x in range(-3, 4)} # {0, 1, 4, 9} (自动去重)
Python的这四大核心数据结构各有特点,适用于不同的场景。掌握它们的特性和使用方法,是成为Python高手的关键一步。