Python3 数据结构详解:从基础到进阶
数据结构是程序的骨架,掌握Python中的数据结构对于编写高效、清晰的代码至关重要。本文将详细介绍Python中最常用的四大数据结构:列表(数组)、元组、集合和字典,包括它们的基本概念、常用操作、进阶技巧以及使用场景。
一、列表(List):Python的动态数组
1.1 基本概念与特点
列表是Python中最常用的数据结构之一,相当于其他编程语言中的动态数组。它具有以下特点:
- 有序的元素集合
- 可以存储任意类型的元素(混合类型也支持)
- 可变(元素可以被修改、添加和删除)
- 使用方括号
[]
表示
1.2 创建与基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| empty_list = [] numbers = [1, 2, 3, 4, 5] mixed_list = [1, "hello", 3.14, True] list_from_range = list(range(10)) list_from_string = list("python")
first_element = numbers[0] last_element = numbers[-1]
sublist = numbers[1:4] every_other = numbers[::2] reversed_list = numbers[::-1]
numbers[0] = 10 print(numbers)
|
1.3 常用函数与方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| numbers.append(6) numbers.insert(1, 11) numbers.extend([7, 8])
numbers.remove(11) popped = numbers.pop() popped_at = numbers.pop(0)
index = numbers.index(4) count = numbers.count(2)
numbers.sort() numbers.sort(reverse=True) numbers.reverse()
length = len(numbers) sum_of_numbers = sum(numbers) max_number = max(numbers) min_number = min(numbers)
|
1.4 进阶用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| squares = [x**2 for x in range(10)] even_squares = [x**2 for x in range(10) if x % 2 == 0]
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [num for row in matrix for num in row] transposed = [[row[i] for row in matrix] for i in range(3)]
square_generator = (x**2 for x in range(10))
shallow_copy = numbers.copy() shallow_copy2 = numbers[:] import copy deep_copy = copy.deepcopy(matrix)
stack = [] stack.append(1) stack.append(2) stack.pop()
from collections import deque queue = deque([1, 2, 3]) queue.append(4) queue.popleft()
|
1.5 列表函数功能总结
函数/方法 |
功能描述 |
示例 |
append() |
在列表末尾添加元素 |
list.append(5) |
insert() |
在指定位置插入元素 |
list.insert(2, 'x') |
extend() |
扩展列表,添加多个元素 |
list.extend([4, 5, 6]) |
remove() |
删除指定值的第一个匹配项 |
list.remove('x') |
pop() |
删除并返回指定索引的元素(默认最后一个) |
list.pop() 或 list.pop(0) |
clear() |
清空列表 |
list.clear() |
index() |
返回指定值的第一个匹配项的索引 |
list.index('x') |
count() |
计算指定值在列表中出现的次数 |
list.count('x') |
sort() |
对列表进行排序 |
list.sort() 或 list.sort(reverse=True) |
reverse() |
反转列表元素顺序 |
list.reverse() |
copy() |
创建列表的浅拷贝 |
new_list = list.copy() |
len() |
返回列表长度 |
length = len(list) |
sum() |
计算列表元素总和(数值型) |
total = sum(list) |
max() |
返回列表中的最大值 |
maximum = max(list) |
min() |
返回列表中的最小值 |
minimum = min(list) |
二、元组(Tuple):不可变的有序集合
2.1 基本概念与特点
元组是另一种有序的数据结构,与列表类似,但具有不可变性。它的特点包括:
- 有序的元素集合
- 可以存储任意类型的元素
- 不可变(创建后不能修改、添加或删除元素)
- 使用圆括号
()
表示(单个元素的元组需要加逗号,如 (1,)
)
2.2 创建与基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| empty_tuple = () single_element_tuple = (1,) numbers_tuple = (1, 2, 3, 4, 5) mixed_tuple = (1, "hello", 3.14, True) tuple_from_list = tuple([1, 2, 3]) tuple_from_string = tuple("python")
first_element = numbers_tuple[0] last_element = numbers_tuple[-1]
sublist = numbers_tuple[1:4] every_other = numbers_tuple[::2]
a, b, c, d, e = numbers_tuple print(a, b, c)
first, *middle, last = numbers_tuple print(first, middle, last)
|
2.3 常用函数与方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| length = len(numbers_tuple) sum_of_numbers = sum(numbers_tuple) max_number = max(numbers_tuple) min_number = min(numbers_tuple) count = numbers_tuple.count(2) index = numbers_tuple.index(3)
tuple1 = (1, 2, 3) tuple2 = (4, 5, 6) concatenated = tuple1 + tuple2 repeated = tuple1 * 2
|
2.4 进阶用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| student_grades = { ("John", "Doe"): 85, ("Jane", "Smith"): 92 }
a, b = 5, 10 a, b = b, a
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"]) p = Point(10, 20) print(p.x, p.y)
def get_min_max(numbers): return min(numbers), max(numbers)
min_val, max_val = get_min_max([1, 2, 3, 4, 5])
|
2.5 元组函数功能总结
函数/方法 |
功能描述 |
示例 |
count() |
计算指定值在元组中出现的次数 |
tuple.count('x') |
index() |
返回指定值的第一个匹配项的索引 |
tuple.index('x') |
len() |
返回元组长度 |
length = len(tuple) |
sum() |
计算元组元素总和(数值型) |
total = sum(tuple) |
max() |
返回元组中的最大值 |
maximum = max(tuple) |
min() |
返回元组中的最小值 |
minimum = min(tuple) |
+ 运算符 |
连接元组 |
tuple3 = tuple1 + tuple2 |
* 运算符 |
重复元组元素 |
tuple2 = tuple1 * 3 |
tuple() |
转换其他序列为元组 |
new_tuple = tuple(list) |
三、集合(Set):无序的唯一元素集合
3.1 基本概念与特点
集合是一个无序的、不重复的元素集合。它的特点包括:
- 无序性(不能通过索引访问元素)
- 唯一性(自动去除重复元素)
- 元素必须是可哈希的(不可变类型)
- 使用花括号
{}
表示(但空集合需要用 set()
创建)
3.2 创建与基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| empty_set = set() numbers_set = {1, 2, 3, 4, 5} set_with_duplicates = {1, 2, 2, 3, 3, 3} set_from_list = set([1, 2, 3, 4, 5]) set_from_string = set("python")
print(3 in numbers_set) print(6 not in numbers_set)
for num in numbers_set: print(num)
|
3.3 常用函数与方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| numbers_set.add(6) numbers_set.update([7, 8, 9])
numbers_set.remove(9) numbers_set.discard(8) popped = numbers_set.pop() numbers_set.clear()
length = len(numbers_set)
s1 = {1, 2, 3, 4, 5} s2 = {4, 5, 6, 7, 8}
intersection = s1 & s2 intersection2 = s1.intersection(s2)
union = s1 | s2 union2 = s1.union(s2)
difference = s1 - s2 difference2 = s1.difference(s2)
symmetric_diff = s1 ^ s2 symmetric_diff2 = s1.symmetric_difference(s2)
is_subset = {1, 2}.issubset(s1) is_superset = s1.issuperset({1, 2})
|
3.4 进阶用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| squares = {x**2 for x in range(10)}
even_numbers = {x for x in range(10) if x % 2 == 0}
frozen = frozenset([1, 2, 3]) d = {frozen: "value"}
duplicated_list = [1, 2, 2, 3, 4, 4, 5] unique_list = list(set(duplicated_list))
large_set = set(range(100000)) print(99999 in large_set)
word_counts = {} words = ["apple", "banana", "apple", "orange", "banana", "apple"] for word in words: word_counts[word] = word_counts.get(word, 0) + 1
|
3.5 集合函数功能总结
函数/方法 |
功能描述 |
示例 |
add() |
向集合添加元素 |
set.add(5) |
update() |
扩展集合,添加多个元素 |
set.update([4, 5, 6]) |
remove() |
删除元素,不存在则抛出异常 |
set.remove(5) |
discard() |
删除元素,不存在则忽略 |
set.discard(5) |
pop() |
随机删除并返回一个元素 |
item = set.pop() |
clear() |
清空集合 |
set.clear() |
len() |
返回集合大小 |
size = len(set) |
in 运算符 |
检查元素是否在集合中 |
if 5 in set: |
& 或 intersection() |
交集运算 |
set3 = set1 & set2 或 set3 = set1.intersection(set2) |
` |
或 union()` |
并集运算 |
- 或 difference() |
差集运算 |
set3 = set1 - set2 或 set3 = set1.difference(set2) |
^ 或 symmetric_difference() |
对称差集运算 |
set3 = set1 ^ set2 或 set3 = set1.symmetric_difference(set2) |
issubset() |
检查是否为子集 |
set1.issubset(set2) |
issuperset() |
检查是否为超集 |
set1.issuperset(set2) |
isdisjoint() |
检查是否不相交(无共同元素) |
set1.isdisjoint(set2) |
set() |
创建集合或转换其他序列为集合 |
new_set = set(list) |
frozenset() |
创建不可变集合 |
frozen = frozenset([1, 2, 3]) |
四、字典(Dictionary):键值对的映射
4.1 基本概念与特点
字典是Python中另一个非常重要的数据结构,它是键值对的集合。它的特点包括:
- 无序性(Python 3.7+保证插入顺序)
- 键的唯一性(相同的键会被覆盖)
- 键必须是可哈希的(不可变类型)
- 值可以是任意类型
- 使用花括号
{}
和冒号 :
表示,如 {key1: value1, key2: value2}
4.2 创建与基本操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| empty_dict = {} student = {"name": "John", "age": 20, "major": "Computer Science"} dict_from_tuples = dict([("a", 1), ("b", 2), ("c", 3)]) dict_with_kwargs = dict(a=1, b=2, c=3) keys = ["a", "b", "c"] values = [1, 2, 3] dict_from_zip = dict(zip(keys, values))
name = student["name"] age = student.get("age") unknown = student.get("address", "Not available")
student["age"] = 21 student["address"] = "123 Main St"
del student["address"] age = student.pop("age") last_item = student.popitem() student.clear()
|
4.3 常用函数与方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| length = len(student)
student = {"name": "John", "age": 20, "major": "Computer Science"} keys = student.keys() values = student.values() items = student.items()
for key in student: print(key, student[key])
for key, value in student.items(): print(key, value)
dict1 = {"a": 1, "b": 2} dict2 = {"b": 3, "c": 4} dict1.update(dict2)
shallow_copy = student.copy() shallow_copy2 = dict(student)
|
4.4 进阶用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| squares = {x: x**2 for x in range(5)}
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
students = { "student1": {"name": "John", "age": 20}, "student2": {"name": "Jane", "age": 21} } print(students["student1"]["name"])
from collections import defaultdict
word_counts = defaultdict(int) words = ["apple", "banana", "apple", "orange", "banana", "apple"] for word in words: word_counts[word] += 1
from collections import defaultdict
students = [ ("CS", "John"), ("CS", "Jane"), ("Math", "Bob"), ("Physics", "Alice") ]
dept_students = defaultdict(list) for dept, name in students: dept_students[dept].append(name)
from collections import OrderedDict
ordered = OrderedDict() ordered["a"] = 1 ordered["b"] = 2 ordered["c"] = 3
|
4.5 字典函数功能总结
函数/方法 |
功能描述 |
示例 |
get(key, default=None) |
获取键对应的值,不存在则返回默认值 |
value = dict.get('key', 'default') |
keys() |
返回所有键的视图 |
keys = dict.keys() |
values() |
返回所有值的视图 |
values = dict.values() |
items() |
返回所有键值对的视图 |
items = dict.items() |
update(other_dict) |
用另一个字典更新当前字典 |
dict.update({"key": "value"}) |
pop(key, default=None) |
删除并返回指定键的值 |
value = dict.pop('key') |
popitem() |
删除并返回最后一个键值对 |
item = dict.popitem() |
clear() |
清空字典 |
dict.clear() |
copy() |
创建字典的浅拷贝 |
new_dict = dict.copy() |
len() |
返回字典中键值对的数量 |
size = len(dict) |
in 运算符 |
检查键是否在字典中 |
if 'key' in dict: |
del 语句 |
删除指定的键值对 |
del dict['key'] |
dict() |
创建字典或转换其他序列为字典 |
new_dict = dict([(1, 'a'), (2, 'b')]) |
zip() 与 dict() 结合 |
从两个序列创建字典 |
new_dict = dict(zip(keys, values)) |
五、Python中的其他有用数据结构
除了以上四种基本数据结构外,Python的collections
模块还提供了一些特殊的容器数据类型,它们是内置数据结构的扩展。
5.1 命名元组(namedtuple)
命名元组为元组中的元素提供了命名访问,兼具元组的不可变性和字典的可读性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from collections import namedtuple
Person = namedtuple("Person", ["name", "age", "job"])
john = Person("John", 30, "Developer")
print(john.name) print(john.age)
john_dict = john._asdict()
|
5.2 双端队列(deque)
双端队列是一种可以在两端高效添加和删除元素的数据结构,适用于实现队列和栈。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| from collections import deque
queue = deque([1, 2, 3])
queue.append(4) queue.appendleft(0)
queue.pop() queue.popleft()
limited_queue = deque(maxlen=3) limited_queue.append(1) limited_queue.append(2) limited_queue.append(3) limited_queue.append(4)
queue.rotate(1)
queue.rotate(-1)
|
5.3 计数器(Counter)
计数器用于统计可哈希对象的出现次数,非常适合频率统计。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| from collections import Counter
words = ["apple", "banana", "apple", "orange", "banana", "apple"] word_counter = Counter(words)
print(word_counter["apple"])
word_counter["apple"] += 1
top_two = word_counter.most_common(2)
counter1 = Counter({"a": 3, "b": 2}) counter2 = Counter({"b": 1, "c": 3})
counter_sum = counter1 + counter2
counter_diff = counter1 - counter2
|
5.4 默认字典(defaultdict)
默认字典在访问不存在的键时会自动创建默认值,避免了KeyError异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from collections import defaultdict
word_lists = defaultdict(list)
word_lists["fruits"].append("apple") word_lists["fruits"].append("banana") word_lists["vegetables"].append("carrot")
def default_value(): return {"count": 0, "items": []}
complex_dict = defaultdict(default_value) complex_dict["A"]["count"] += 1 complex_dict["A"]["items"].append("item1")
|
5.5 collections模块扩展数据结构函数功能总结
5.5.1 命名元组(namedtuple)
函数/方法 |
功能描述 |
示例 |
namedtuple(typename, field_names) |
创建命名元组类 |
Point = namedtuple("Point", ["x", "y"]) or namedtuple("Point", "x y") |
_asdict() |
转换命名元组为有序字典 |
point_dict = point._asdict() |
_fields |
返回字段名的元组 |
fields = Point._fields |
_replace(**kwargs) |
创建并返回修改指定字段的新实例 |
new_point = point._replace(x=100) |
_make(iterable) |
从可迭代对象创建新的命名元组实例 |
new_point = Point._make([10, 20]) |
5.5.2 双端队列(deque)
函数/方法 |
功能描述 |
示例 |
append(x) |
在右端添加元素 |
deque.append(5) |
appendleft(x) |
在左端添加元素 |
deque.appendleft(0) |
pop() |
移除并返回右端元素 |
item = deque.pop() |
popleft() |
移除并返回左端元素 |
item = deque.popleft() |
extend(iterable) |
在右端扩展元素 |
deque.extend([6, 7, 8]) |
extendleft(iterable) |
在左端扩展元素(逆序) |
deque.extendleft([-2, -1]) |
rotate(n=1) |
向右旋转n步(负数向左旋转) |
deque.rotate(1) 或 deque.rotate(-1) |
clear() |
清空双端队列 |
deque.clear() |
count(x) |
计算元素出现次数 |
count = deque.count(5) |
remove(value) |
移除第一个匹配的元素 |
deque.remove(5) |
maxlen |
双端队列的最大长度(只读属性) |
max_length = deque.maxlen |
5.5.3 计数器(Counter)
函数/方法 |
功能描述 |
示例 |
Counter(iterable) |
创建计数器对象 |
counter = Counter([1, 2, 1, 3, 2, 1]) |
most_common(n=None) |
返回n个最常见的元素及其计数 |
top_3 = counter.most_common(3) |
elements() |
返回迭代器,包含所有元素(按计数重复) |
elements = list(counter.elements()) |
update(iterable) |
更新计数器,增加元素计数 |
counter.update([1, 4, 5]) |
subtract(iterable) |
减少元素计数 |
counter.subtract([1, 2]) |
clear() |
清空计数器 |
counter.clear() |
+ 运算符 |
合并计数器(只保留正数计数) |
counter3 = counter1 + counter2 |
- 运算符 |
计数器差集(只保留正数计数) |
counter3 = counter1 - counter2 |
& 运算符 |
计数器交集(保留最小计数) |
counter3 = counter1 & counter2 |
` |
` 运算符 |
计数器并集(保留最大计数) |
5.5.4 默认字典(defaultdict)
函数/方法 |
功能描述 |
示例 |
defaultdict(default_factory) |
创建默认字典,指定默认值工厂函数 |
dd = defaultdict(list) 或 dd = defaultdict(lambda: 0) |
访问不存在的键 |
自动创建并返回默认值 |
value = dd['new_key'] (自动创建) |
所有普通字典方法 |
与普通字典相同的方法 |
dd.keys() , dd.values() , dd.items() , dd.update() , 等 |
六、数据结构的选择指南
在实际编程中,选择合适的数据结构对于提高代码效率至关重要。以下是一些常见场景下的数据结构选择建议:
使用场景 |
推荐数据结构 |
理由 |
存储有序的、需要频繁修改的元素集合 |
列表(List) |
支持索引访问和高效的尾部添加/删除 |
存储不可变的数据,或作为字典键 |
元组(Tuple) |
不可变性提供了哈希能力和数据安全性 |
存储唯一元素,需要快速的成员检查 |
集合(Set) |
O(1)时间复杂度的成员检查和去重功能 |
存储键值对,需要快速的查找 |
字典(Dictionary) |
O(1)时间复杂度的键查找 |
实现队列或需要高效的两端操作 |
双端队列(deque) |
两端操作的时间复杂度为O(1) |
统计频率或计数 |
计数器(Counter) |
专门为计数设计的高效数据结构 |
分组数据 |
默认字典(defaultdict) |
避免了手动检查键是否存在的代码 |
七、总结
Python提供了丰富的数据结构,每种数据结构都有其特定的用途和优势。掌握这些数据结构的基本概念、操作方法和适用场景,对于编写高效、清晰的Python代码至关重要。在实际开发中,我们应该根据具体需求选择合适的数据结构,并且不要忘记Python的collections
模块中那些强大的扩展数据结构,它们往往能帮助我们更优雅地解决问题。