作者:还怪好嘞 专栏:Python全栈修炼之路 标签:Python、列表、元组、动态数组、性能优化
前言
列表(list)和元组(tuple)是Python中最基础、最常用的序列类型。它们看似相似,却有着本质的区别。理解它们的底层实现、性能特征和适用场景,是写出高效Python代码的关键。本文将深入剖析这对"双子星",并通过实战项目加深理解。
一、知识点详解
1.1 列表基础操作(CRUD)
1.1.1 创建列表(Create)
# 1. 字面量创建empty_list = []numbers = [1, 2, 3, 4, 5]mixed = [1, "hello", 3.14, True, [1, 2]]# 2. list()构造函数from_string = list("hello") # ['h', 'e', 'l', 'l', 'o']from_range = list(range(5)) # [0, 1, 2, 3, 4]from_tuple = list((1, 2, 3)) # [1, 2, 3]# 3. 列表推导式(高效且Pythonic)squares = [x**2 for x in range(10)]evens = [x for x in range(20) if x % 2 == 0]# 4. 乘法创建(注意:浅拷贝陷阱)zeros = [0] * 5 # [0, 0, 0, 0, 0]# 陷阱:[[0]] * 3 创建的是3个相同子列表的引用
1.1.2 读取列表(Read)
fruits = ["apple", "banana", "cherry", "date", "elderberry"]# 索引访问print(fruits[0]) # "apple"print(fruits[-1]) # "elderberry"(最后一个)# 切片操作(与字符串相同)print(fruits[1:4]) # ['banana', 'cherry', 'date']print(fruits[:3]) # ['apple', 'banana', 'cherry']print(fruits[::2]) # ['apple', 'cherry', 'elderberry']print(fruits[::-1]) # 反转# 成员判断print("apple" in fruits) # Trueprint("grape" not in fruits) # True# 遍历for fruit in fruits: print(fruit)# 带索引遍历for index, fruit in enumerate(fruits): print(f"{index}: {fruit}")
1.1.3 更新列表(Update)
# 修改元素numbers = [1, 2, 3]numbers[0] = 10 # [10, 2, 3]# 切片修改numbers[1:3] = [20, 30] # [10, 20, 30]numbers[1:2] = [2, 3, 4] # [10, 2, 3, 4, 30](插入多个)# 添加元素numbers.append(40) # 末尾添加单个numbers.extend([50, 60]) # 末尾添加多个numbers.insert(0, 0) # 指定位置插入# 其他添加方式numbers += [70, 80] # 等价于extendnumbers[len(numbers):] = [90] # 切片添加
1.1.4 删除列表(Delete)
items = ["a", "b", "c", "d", "e"]# 删除元素del items[0] # 按索引删除del items[1:3] # 切片删除item = items.pop() # 删除并返回最后一个item = items.pop(0) # 删除并返回指定索引items.remove("c") # 按值删除(第一个匹配)# 清空列表items.clear() # 清空items = [] # 重新赋值(原列表被GC)# 删除整个列表del items
1.2 列表方法速查表
| | | |
|---|
append(x) | | | lst.append(4) |
extend(iter) | | | lst.extend([4,5]) |
insert(i, x) | | | lst.insert(0, 'a') |
remove(x) | | | lst.remove(3) |
pop([i]) | | | lst.pop() |
clear() | | | lst.clear() |
index(x) | | | lst.index('a') |
count(x) | | | lst.count(3) |
sort() | | | lst.sort() |
reverse() | | | lst.reverse() |
copy() | | | lst2 = lst.copy() |
1.3 切片进阶技巧
# 切片赋值的高级用法nums = [1, 2, 3, 4, 5]# 1. 替换子列表nums[1:4] = [20, 30] # [1, 20, 30, 5]# 2. 插入元素(不删除)nums = [1, 2, 5]nums[2:2] = [3, 4] # [1, 2, 3, 4, 5]# 3. 删除子列表(赋值为空)nums = [1, 2, 3, 4, 5]nums[1:4] = [] # [1, 5]# 4. 步长切片(间隔操作)nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]nums[::2] = [0, 0, 0, 0, 0] # 修改偶数索引位置print(nums) # [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]# 5. 反转删除(安全遍历)nums = [1, 2, 3, 2, 4, 2, 5]for i in range(len(nums) - 1, -1, -1): if nums[i] == 2: del nums[i]print(nums) # [1, 3, 4, 5]
1.4 列表推导式详解
列表推导式是Python的标志性特性,简洁且高效:
# 基本语法# [expression for item in iterable]# [expression for item in iterable if condition]# 示例1:平方数squares = [x**2 for x in range(10)]# 示例2:带条件even_squares = [x**2 for x in range(10) if x % 2 == 0]# 示例3:多重循环pairs = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]# 示例4:嵌套推导式matrix = [[i*j for j in range(1, 4)] for i in range(1, 4)]# [[1, 2, 3], [2, 4, 6], [3, 6, 9]]# 示例5:扁平化matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]flat = [x for row in matrix for x in row]# [1, 2, 3, 4, 5, 6, 7, 8, 9]# 示例6:字典推导式(扩展)square_dict = {x: x**2 for x in range(5)}# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}# 示例7:集合推导式square_set = {x**2 for x in range(100)}
推导式 vs 循环性能对比:
import timeit# 测试数据n = 10000# 方式1:for循环def loop_way(): result = [] for i in range(n): if i % 2 == 0: result.append(i * 2) return result# 方式2:列表推导式def comp_way(): return [i * 2 for i in range(n) if i % 2 == 0]# 方式3:map+filterdef map_way(): return list(map(lambda x: x * 2, filter(lambda x: x % 2 == 0, range(n))))print(f"循环: {timeit.timeit(loop_way, number=100):.4f}s")print(f"推导式: {timeit.timeit(comp_way, number=100):.4f}s")print(f"map/filter: {timeit.timeit(map_way, number=100):.4f}s")# 结果:推导式 > map/filter > 循环(通常推导式最快)
1.5 元组特性详解
1.5.1 元组基础
# 创建元组empty = ()single = (1,) # 注意:单元素必须加逗号!multiple = (1, 2, 3)no_parens = 1, 2, 3 # 括号可省略# 元组解包a, b = (1, 2)a, b = b, a # 交换变量(Pythonic)# 扩展解包(Python 3)first, *rest = (1, 2, 3, 4, 5) # first=1, rest=[2,3,4,5]*begin, last = (1, 2, 3, 4, 5) # begin=[1,2,3,4], last=5first, *middle, last = range(5) # first=0, middle=[1,2,3], last=4# 嵌套元组coords = ((1, 2), (3, 4), (5, 6))
1.5.2 元组的"不可变性"
# 元组不可变的是引用,不是对象t = ([1, 2], [3, 4])# t[0] = [5, 6] # TypeError: 不能修改引用t[0].append(3) # 可以!修改的是列表对象print(t) # ([1, 2, 3], [3, 4])# 创建真正不可变的元组t = (tuple([1, 2]), tuple([3, 4]))# t[0].append(3) # AttributeError
1.5.3 namedtuple —— 具名元组
from collections import namedtuple# 定义具名元组Point = namedtuple('Point', ['x', 'y'])Person = namedtuple('Person', 'name age city') # 空格分隔也可# 创建实例p = Point(3, 4)print(p.x, p.y) # 3 4print(p[0], p[1]) # 也可以用索引# 不可变性# p.x = 5 # AttributeError# 方法p2 = p._replace(x=5) # 创建新实例print(p2) # Point(x=5, y=4)# 转字典print(p._asdict()) # {'x': 3, 'y': 4}# 使用场景:轻量级数据结构users = [ Person("Alice", 25, "Beijing"), Person("Bob", 30, "Shanghai"),]for user in users: print(f"{user.name} ({user.age}) from {user.city}")# Python 3.7+ 的替代:dataclasses(更灵活)from dataclasses import dataclass@dataclass(frozen=True) # frozen=True使其不可变def Point: x: int y: int
二、底层原理深度解析
2.1 列表的动态数组实现
核心概念: Python列表是基于动态数组(dynamic array)实现的,而非链表。
内存布局示意:列表对象头部┌─────────────────┐│ ob_refcnt │ 引用计数│ ob_type │ 类型指针│ ob_size │ 元素个数 = 3│ allocated │ 容量 = 8│ ob_item ────────┼──→ 指向数组指针└─────────────────┘数组存储(连续内存)┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐│ 10 │ 20 │ 30 │ │ │ │ │ │└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ 0 1 2 3 4 5 6 7 └─已用─┘ └────────未用────────┘
扩容策略:
# CPython的扩容策略:# 当前容量 < 9: 扩容到 9# 当前容量 >= 9: 扩容为 1.125 倍(近似)# 实际公式:newsize + (newsize >> 3) + (3 if newsize < 9 else 6)import sysdef show_list_growth(): lst = [] for i in range(100): lst.append(i) if i in [0, 4, 8, 16, 25, 35, 46, 58, 72, 88]: print(f"元素数: {len(lst):3}, 容量: {sys.getsizeof(lst)}")show_list_growth()
时间复杂度分析:
2.2 元组的不可变性优势
为什么使用元组?
性能更优
线程安全
语义明确
import sysimport timeit# 内存对比lst = [1, 2, 3, 4, 5]t = (1, 2, 3, 4, 5)print(f"列表大小: {sys.getsizeof(lst)} bytes")print(f"元组大小: {sys.getsizeof(t)} bytes")# 创建速度对比list_time = timeit.timeit("[1, 2, 3, 4, 5]", number=1000000)tuple_time = timeit.timeit("(1, 2, 3, 4, 5)", number=1000000)print(f"\n列表创建: {list_time:.4f}s")print(f"元组创建: {tuple_time:.4f}s")print(f"元组快 {list_time/tuple_time:.2f} 倍")
2.3 列表 vs 元组性能对比
import timeitimport sysdef benchmark(): # 创建性能 print("=== 创建性能 ===") list_time = timeit.timeit("[1, 2, 3, 4, 5]", number=1000000) tuple_time = timeit.timeit("(1, 2, 3, 4, 5)", number=1000000) print(f"列表: {list_time:.4f}s") print(f"元组: {tuple_time:.4f}s") # 迭代性能 print("\n=== 迭代性能 ===") list_iter = timeit.timeit("for x in lst: pass", setup="lst=[1,2,3,4,5]*100", number=10000) tuple_iter = timeit.timeit("for x in t: pass", setup="t=(1,2,3,4,5)*100", number=10000) print(f"列表: {list_iter:.4f}s") print(f"元组: {tuple_iter:.4f}s") # 内存占用 print("\n=== 内存占用 ===") big_list = list(range(10000)) big_tuple = tuple(range(10000)) print(f"列表: {sys.getsizeof(big_list)} bytes") print(f"元组: {sys.getsizeof(big_tuple)} bytes") # 访问速度 print("\n=== 索引访问 ===") list_access = timeit.timeit("lst[5000]", setup="lst=list(range(10000))", number=1000000) tuple_access = timeit.timeit("t[5000]", setup="t=tuple(range(10000))", number=1000000) print(f"列表: {list_access:.4f}s") print(f"元组: {tuple_access:.4f}s")benchmark()
性能对比结论:
三、实战项目
3.1 项目一:学生成绩管理系统
from typing import List, Dict, Tuple, Optionalfrom collections import namedtupleimport statistics# 定义数据结构Student = namedtuple('Student', ['id', 'name', 'scores'])class GradeManager: """学生成绩管理系统""" def __init__(self): self.students: List[Student] = [] self.subjects = ["语文", "数学", "英语", "物理", "化学"] def add_student(self, student_id: str, name: str, scores: Tuple[float, ...]) -> None: """添加学生""" if len(scores) != len(self.subjects): raise ValueError(f"成绩数量应为{len(self.subjects)}") student = Student(student_id, name, scores) self.students.append(student) print(f"已添加学生: {name}") def remove_student(self, student_id: str) -> bool: """删除学生""" for i, s in enumerate(self.students): if s.id == student_id: del self.students[i] print(f"已删除学生: {s.name}") return True print(f"未找到学生: {student_id}") return False def update_score(self, student_id: str, subject: str, score: float) -> bool: """更新单科成绩""" if subject not in self.subjects: print(f"无效科目: {subject}") return False for i, s in enumerate(self.students): if s.id == student_id: subject_idx = self.subjects.index(subject) new_scores = list(s.scores) new_scores[subject_idx] = score # 元组不可变,需要重新创建 self.students[i] = Student(s.id, s.name, tuple(new_scores)) print(f"已更新{s.name}的{subject}成绩为{score}") return True return False def get_student_avg(self, student: Student) -> float: """计算学生平均分""" return statistics.mean(student.scores) def get_student_total(self, student: Student) -> float: """计算学生总分""" return sum(student.scores) def get_ranking(self) -> List[Tuple[Student, float]]: """获取排名(按总分)""" ranked = [(s, self.get_student_total(s)) for s in self.students] return sorted(ranked, key=lambda x: x[1], reverse=True) def get_subject_stats(self) -> Dict[str, Dict]: """获取各科统计""" stats = {} for i, subject in enumerate(self.subjects): scores = [s.scores[i] for s in self.students] stats[subject] = { "最高分": max(scores), "最低分": min(scores), "平均分": round(statistics.mean(scores), 2), "中位数": statistics.median(scores) } return stats def find_students_by_score(self, min_score: float, max_score: float) -> List[Student]: """按总分范围查找学生""" return [s for s in self.students if min_score <= self.get_student_total(s) <= max_score] def print_report(self): """打印成绩报表""" print("\n" + "=" * 80) print("学生成绩单".center(80)) print("=" * 80) # 表头 header = f"{'学号':<10}{'姓名':<10}" for subj in self.subjects: header += f"{subj:>8}" header += f"{'总分':>10}{'平均分':>10}" print(header) print("-" * 80) # 学生数据 for s in self.students: line = f"{s.id:<10}{s.name:<10}" for score in s.scores: line += f"{score:>8.1f}" line += f"{self.get_student_total(s):>10.1f}" line += f"{self.get_student_avg(s):>10.2f}" print(line) print("-" * 80) # 统计信息 print("\n各科统计:") for subject, stat in self.get_subject_stats().items(): print(f" {subject}: 最高{stat['最高分']}, 最低{stat['最低分']}, " f"平均{stat['平均分']}, 中位数{stat['中位数']}") # 排名 print("\n总分排名:") for rank, (s, total) in enumerate(self.get_ranking(), 1): print(f" 第{rank}名: {s.name} ({total:.1f}分)")# 使用示例if __name__ == "__main__": manager = GradeManager() # 添加学生 manager.add_student("2024001", "张三", (85, 92, 78, 88, 90)) manager.add_student("2024002", "李四", (78, 85, 92, 75, 88)) manager.add_student("2024003", "王五", (92, 88, 85, 95, 90)) manager.add_student("2024004", "赵六", (65, 72, 68, 70, 75)) # 更新成绩 manager.update_score("2024001", "数学", 95) # 打印报表 manager.print_report() # 查找优秀学生(总分>400) print("\n优秀学生(总分>400):") excellent = manager.find_students_by_score(400, 500) for s in excellent: print(f" - {s.name}: {manager.get_student_total(s):.1f}分")
3.2 项目二:约瑟夫环问题
from typing import List, Tuplefrom collections import dequeclass JosephusProblem: """ 约瑟夫环问题求解器 问题描述:n个人围成一圈,从第k个人开始报数,数到m的人出列, 接着从下一个人开始报数,直到所有人出列。求出列顺序。 """ @staticmethod def solve_list(n: int, m: int, k: int = 1) -> List[int]: """ 使用列表求解(直观但效率较低) Args: n: 总人数(编号1-n) m: 报数间隔 k: 起始位置(1-based) """ # 创建人员列表 people = list(range(1, n + 1)) result = [] # 当前索引(调整到起始位置) index = k - 1 while people: # 计算出列者索引 index = (index + m - 1) % len(people) # 出列 result.append(people.pop(index)) return result @staticmethod def solve_deque(n: int, m: int, k: int = 1) -> List[int]: """ 使用双端队列求解(更高效) """ # 初始化队列 queue = deque(range(1, n + 1)) result = [] # 调整到起始位置 queue.rotate(-(k - 1)) while queue: # 将前m-1个人移到队尾 queue.rotate(-(m - 1)) # 第m个人出列 result.append(queue.popleft()) return result @staticmethod def solve_recursive(n: int, m: int) -> int: """ 递归公式求解(只返回最后幸存者) J(n, m) = (J(n-1, m) + m) % n, J(1, m) = 0 返回0-based索引,需要+1得到编号 """ if n == 1: return 0 return (JosephusProblem.solve_recursive(n - 1, m) + m) % n @staticmethod def solve_iterative(n: int, m: int) -> int: """ 迭代公式求解(只返回最后幸存者) """ survivor = 0 # J(1, m) = 0 for i in range(2, n + 1): survivor = (survivor + m) % i return survivor + 1 # 转换为1-based @staticmethod def solve_full_trace(n: int, m: int, k: int = 1) -> Tuple[List[int], List[str]]: """ 完整追踪每一步(用于教学演示) """ people = list(range(1, n + 1)) result = [] trace = [] index = k - 1 round_num = 1 trace.append(f"初始: {people}") while people: trace.append(f"\n第{round_num}轮:") trace.append(f" 当前序列: {people}") trace.append(f" 从索引{index}(编号{people[index]})开始数{m}个") index = (index + m - 1) % len(people) out = people.pop(index) result.append(out) trace.append(f" → 编号{out}出列") if people: trace.append(f" 剩余: {people}") trace.append(f" 下一轮从索引{index % len(people)}开始") round_num += 1 trace.append(f"\n出列顺序: {result}") return result, tracedef demo(): """演示约瑟夫环问题""" print("=" * 60) print("约瑟夫环问题演示") print("=" * 60) # 参数设置 n, m, k = 7, 3, 1 print(f"\n参数: n={n}人, m={m}, 从第{k}人开始\n") # 完整追踪 result, trace = JosephusProblem.solve_full_trace(n, m, k) for line in trace: print(line) # 方法对比 print("\n" + "=" * 60) print("不同解法结果对比") print("=" * 60) print(f"\n列表法出列顺序: {JosephusProblem.solve_list(n, m, k)}") print(f"双端队列法: {JosephusProblem.solve_deque(n, m, k)}") print(f"最后幸存者(递归): {JosephusProblem.solve_recursive(n, m) + 1}") print(f"最后幸存者(迭代): {JosephusProblem.solve_iterative(n, m)}") # 性能对比 print("\n" + "=" * 60) print("性能对比(n=1000, m=7)") print("=" * 60) import timeit n, m = 1000, 7 list_time = timeit.timeit( lambda: JosephusProblem.solve_list(n, m), number=100) deque_time = timeit.timeit( lambda: JosephusProblem.solve_deque(n, m), number=100) iter_time = timeit.timeit( lambda: JosephusProblem.solve_iterative(n, m), number=100) print(f"列表法: {list_time:.4f}s") print(f"双端队列法: {deque_time:.4f}s") print(f"迭代公式法: {iter_time:.6f}s")if __name__ == "__main__": demo()
四、常见陷阱与解决方案
4.1 浅拷贝陷阱
# 陷阱1:乘法创建嵌套列表matrix = [[0] * 3] * 3matrix[0][0] = 1print(matrix) # [[1, 0, 0], [1, 0, 0], [1, 0, 0]] 全是1!# 原因:3个引用指向同一个子列表print(matrix[0] is matrix[1]) # True# 正确做法:列表推导式matrix = [[0] * 3 for _ in range(3)]matrix[0][0] = 1print(matrix) # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]# 陷阱2:copy()是浅拷贝import copyoriginal = [[1, 2], [3, 4]]shallow = original.copy()shallow[0][0] = 999print(original) # [[999, 2], [3, 4]] 原列表也被修改了!# 正确做法:深拷贝deep = copy.deepcopy(original)deep[0][0] = 111print(original) # [[999, 2], [3, 4]] 原列表不变
4.2 迭代时修改列表
# 陷阱:遍历列表时删除元素nums = [1, 2, 3, 4, 5]for num in nums: if num % 2 == 0: nums.remove(num) # 危险!print(nums) # [1, 3, 5] 看起来对了?# 但看这个情况nums = [2, 2, 3, 4]for num in nums: if num == 2: nums.remove(num)print(nums) # [2, 3, 4] 还有一个2!# 原因:删除元素后索引前移,跳过了下一个元素# 正确做法1:倒序遍历nums = [2, 2, 3, 4]for i in range(len(nums) - 1, -1, -1): if nums[i] == 2: del nums[i]print(nums) # [3, 4]# 正确做法2:列表推导式nums = [2, 2, 3, 4]nums = [x for x in nums if x != 2]print(nums) # [3, 4]# 正确做法3:filter函数nums = [2, 2, 3, 4]nums = list(filter(lambda x: x != 2, nums))print(nums) # [3, 4]
4.3 默认参数陷阱
# 陷阱:可变对象作为默认参数def append_item(item, lst=[]): lst.append(item) return lstprint(append_item(1)) # [1]print(append_item(2)) # [1, 2] 保留了上次的结果!# 原因:默认参数在函数定义时创建,只创建一次# 正确做法:使用Nonedef append_item(item, lst=None): if lst is None: lst = [] lst.append(item) return lstprint(append_item(1)) # [1]print(append_item(2)) # [2] 正确!
4.4 元组单元素陷阱
# 陷阱:忘记逗号not_tuple = (1) # 这不是元组,是整数1!print(type(not_tuple)) # <class 'int'>real_tuple = (1,) # 这才是单元素元组print(type(real_tuple)) # <class 'tuple'># 陷阱:元组拼接a = (1, 2)b = (3) # 整数3try: c = a + b # TypeErrorexcept TypeError as e: print(f"错误: {e}")# 正确b = (3,) # 或 b = 3,c = a + b # (1, 2, 3)
4.5 列表排序陷阱
# 陷阱1:sort() vs sorted()original = [3, 1, 4, 1, 5]# sort() 原地排序,返回Noneresult = original.sort()print(result) # Noneprint(original) # [1, 1, 3, 4, 5]# sorted() 返回新列表original = [3, 1, 4, 1, 5]result = sorted(original)print(result) # [1, 1, 3, 4, 5]print(original) # [3, 1, 4, 1, 5] 原列表不变# 陷阱2:复杂对象排序students = [ {"name": "Alice", "score": 85}, {"name": "Bob", "score": 92}, {"name": "Charlie", "score": 78},]# 错误:不能直接比较字典# students.sort() # TypeError# 正确:使用key参数students.sort(key=lambda s: s["score"], reverse=True)print(students)# 或者使用operator模块(更快)from operator import itemgetterstudents.sort(key=itemgetter("score"), reverse=True)
五、本章小结
核心知识点回顾
| |
|---|
| append/extend/insert、索引访问、切片操作、pop/remove/del |
| sort/reverse/index/count/copy、时间复杂度 |
| [x for x in iter if cond] |
| |
| |
| |
列表 vs 元组选择指南
使用列表当: ✓ 需要频繁增删元素 ✓ 数据需要修改 ✓ 作为工作数据的容器使用元组当: ✓ 数据不应被修改(记录语义) ✓ 需要作为字典key ✓ 需要哈希(如放入set) ✓ 追求极致性能 ✓ 函数返回多个值
最佳实践清单
- 选择合适的数据结构(列表vs元组vs集合vs字典)
六、课后练习
基础练习
列表去重:编写函数去除列表重复元素,保持原有顺序
unique([1, 2, 2, 3, 3, 3]) # [1, 2, 3]
扁平化嵌套列表:将多层嵌套列表展开为一维
flatten([1, [2, 3], [[4, 5], 6]]) # [1, 2, 3, 4, 5, 6]
矩阵转置:实现矩阵转置
transpose([[1, 2, 3], [4, 5, 6]]) # [[1, 4], [2, 5], [3, 6]]
进阶练习
滑动窗口:给定列表和窗口大小,返回所有窗口
sliding_window([1, 2, 3, 4, 5], 3) # [[1,2,3], [2,3,4], [3,4,5]]
合并有序列表:合并两个有序列表,保持有序
merge_sorted([1, 3, 5], [2, 4, 6]) # [1, 2, 3, 4, 5, 6]
实现简易列表类:实现支持基本操作的MyList类
挑战练习
LRU缓存:使用有序字典实现LRU缓存
稀疏矩阵:使用字典实现稀疏矩阵,支持基本运算
参考资源
- Time Complexity of Python Operations
下篇预告:第5篇《字典与集合 —— 哈希的威力》,深入讲解Python最高效的数据结构,包括哈希表原理、字典有序性保证、集合运算等。
本文是《Python全栈修炼之路》系列第4篇,持续更新中,欢迎关注专栏获取更多内容!