1. Python容器进阶实战:从基础到高性能
Python开发者每天都要和各种容器打交道,但很多人停留在基础的增删改查操作上。作为一名长期使用Python处理海量数据的开发者,我发现合理运用容器的高级特性,能让代码执行效率提升数倍。今天就来分享我在实际项目中积累的Python容器进阶技巧。
Python的容器类型主要包括列表(list)、字典(dict)、集合(set)和元组(tuple),每种容器都有其独特的优势和适用场景。掌握它们的进阶用法,不仅能写出更简洁的代码,还能显著提升程序性能。特别是在处理大数据量时,正确的容器选择和使用方法可以带来数量级的性能差异。
2. 列表(list)的高阶技巧与性能优化
2.1 列表推导式的威力
列表推导式是Python中最优雅的特性之一,但很多开发者只停留在基础用法。实际上,它可以处理非常复杂的场景:
python复制# 复杂条件筛选:找出1-100中既是偶数又是质数的数字
def is_prime(n):
return n > 1 and all(n % i for i in range(2, int(n**0.5)+1))
result = [x for x in range(2, 101) if x % 2 == 0 and is_prime(x)]
print(result) # [2]
列表推导式相比普通for循环有几个显著优势:
- 执行速度更快,因为解释器对其有专门优化
- 代码更简洁,通常能减少50%以上的代码量
- 可读性更强,将数据处理逻辑集中在一行
注意:当推导式变得过于复杂时(如嵌套超过2层或条件判断太多),应考虑拆分为普通循环以保证可读性。
2.2 切片操作的进阶用法
切片操作远不止简单的取子列表,它还能实现很多高效操作:
python复制data = list(range(10))
# 每隔n个元素取一个
print(data[::2]) # [0, 2, 4, 6, 8]
# 反转列表的优雅写法
print(data[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 批量替换部分元素
data[2:5] = [99, 99, 99]
print(data) # [0, 1, 99, 99, 99, 5, 6, 7, 8, 9]
切片操作不会修改原列表,而是返回一个新列表,这在函数式编程中特别有用。
2.3 列表操作的性能陷阱
列表操作中有几个常见的性能陷阱需要注意:
- 频繁append vs extend:
- append每次添加一个元素,会有多次函数调用开销
- extend一次性添加多个元素,效率更高
python复制# 低效做法
result = []
for item in large_dataset:
result.append(process(item))
# 高效做法
result = []
result.extend(process(item) for item in large_dataset)
- 列表拼接的几种方式对比:
+操作符:创建新列表,适合小型列表+=或extend:修改原列表,适合大型列表itertools.chain:惰性求值,内存效率最高
python复制from itertools import chain
large_list1 = list(range(100000))
large_list2 = list(range(100000))
# 内存效率最高的方式
combined = chain(large_list1, large_list2)
- 浅拷贝与深拷贝:
- 切片和copy()都是浅拷贝
- 嵌套结构需要深拷贝
python复制import copy
original = [[1, 2], [3, 4]]
shallow = original.copy()
deep = copy.deepcopy(original)
original[0][0] = 99
print(shallow) # [[99, 2], [3, 4]] 受影响
print(deep) # [[1, 2], [3, 4]] 不受影响
3. 字典(dict)的高级用法与性能优化
3.1 安全访问字典元素
字典访问中最常见的问题是KeyError,有几种优雅的解决方案:
python复制user = {"name": "Alice", "age": 30}
# 基础安全访问
print(user.get("email", "default@example.com")) # 键不存在返回默认值
# 更复杂的默认值处理
from collections import defaultdict
def default_factory():
return {"count": 0, "log": []}
stats = defaultdict(default_factory)
stats["login"]["count"] += 1
stats["login"]["log"].append("2023-01-01")
3.2 字典推导式的妙用
字典推导式可以简洁地转换和过滤数据:
python复制# 转换列表为字典
keys = ["a", "b", "c"]
values = [1, 2, 3]
mapping = {k: v**2 for k, v in zip(keys, values)}
print(mapping) # {'a': 1, 'b': 4, 'c': 9}
# 复杂条件过滤
data = {"a": 1, "b": 2, "c": 3, "d": 4}
filtered = {k: v for k, v in data.items() if v % 2 == 0 and k != "d"}
print(filtered) # {'b': 2}
3.3 字典视图的高效使用
Python 3中的字典视图(dict.keys(), dict.values(), dict.items())是动态的,会反映字典的变化:
python复制inventory = {"apple": 10, "banana": 5}
keys = inventory.keys()
print(list(keys)) # ['apple', 'banana']
inventory["orange"] = 8
print(list(keys)) # ['apple', 'banana', 'orange'] 自动更新
视图对象非常轻量,几乎不占用额外内存,特别适合遍历大型字典。
3.4 有序字典的应用场景
虽然Python 3.7+的普通字典已经保持插入顺序,但collections.OrderedDict仍有独特用途:
python复制from collections import OrderedDict
# LRU缓存实现
class LRUCache:
def __init__(self, capacity):
self.cache = OrderedDict()
self.capacity = capacity
def get(self, key):
if key not in self.cache:
return -1
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key, value):
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
self.cache.popitem(last=False)
4. 集合(set)的高效应用
4.1 快速去重与成员测试
集合的去重能力比列表高效得多:
python复制# 列表去重的低效方法
def unique_list(items):
seen = []
for item in items:
if item not in seen:
seen.append(item)
return seen
# 使用集合的高效方法
def unique_set(items):
return list(set(items))
对于100万个元素的数据,集合方法比列表方法快约100倍。
4.2 集合运算的实际应用
集合运算可以简化很多复杂逻辑:
python复制# 用户权限检查示例
admin_perms = {"create", "delete", "update"}
user_perms = {"read", "update"}
# 检查是否有管理员权限
print(admin_perms & user_perms) # {'update'}
# 检查缺少哪些权限
print(admin_perms - user_perms) # {'create', 'delete'}
# 检查所有唯一权限
print(admin_perms ^ user_perms) # {'create', 'delete', 'read'}
4.3 冻结集合的特殊用途
frozenset是不可变集合,可以作为字典的键:
python复制# 用frozenset表示复合键
permission_groups = {
frozenset(["read", "write"]): "standard",
frozenset(["admin"]): "administrator"
}
key = frozenset(["read", "write"])
print(permission_groups[key]) # "standard"
5. 元组(tuple)与命名元组的高级应用
5.1 元组的不可变优势
元组的不可变性带来几个关键优势:
- 线程安全
- 可以作为字典的键
- 更小的内存占用
python复制# 坐标系统示例
points = {
(0, 0): "origin",
(1, 2): "point A",
(3, 4): "point B"
}
print(points[(1, 2)]) # "point A"
5.2 命名元组的替代方案
Python 3.7+引入了dataclasses,可以作为命名元组的现代替代:
python复制from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
z: float = 0.0 # 默认值
p = Point(1.5, 2.5)
print(p.x, p.y) # 1.5 2.5
dataclass比namedtuple更灵活,支持默认值、类型提示等现代特性。
5.3 元组解包的进阶用法
元组解包可以用于很多优雅的模式:
python复制# 变量交换
a, b = 1, 2
a, b = b, a
# 函数返回多个值
def stats(data):
return min(data), max(data), sum(data)/len(data)
minimum, maximum, average = stats([1, 2, 3, 4, 5])
# 带*的解包
first, *middle, last = range(10)
print(first) # 0
print(middle) # [1, 2, 3, 4, 5, 6, 7, 8]
print(last) # 9
6. 容器性能对比与选型指南
6.1 时间复杂度对比
| 操作 | 列表(list) | 字典(dict) | 集合(set) | 元组(tuple) |
|---|---|---|---|---|
| 索引/键访问 | O(1) | O(1) | N/A | O(1) |
| 追加 | O(1)* | N/A | N/A | 不可变 |
| 插入 | O(n) | O(1) | O(1) | 不可变 |
| 删除 | O(n) | O(1) | O(1) | 不可变 |
| 成员检查 | O(n) | O(1) | O(1) | O(n) |
| 迭代 | O(n) | O(n) | O(n) | O(n) |
*列表的append操作平均为O(1),但在需要扩容时为O(n)
6.2 内存占用对比
| 容器类型 | 内存特点 | 适用场景 |
|---|---|---|
| 列表 | 动态数组,预留空间 | 频繁修改的有序序列 |
| 元组 | 固定大小,无预留空间 | 不可变数据,字典键 |
| 字典 | 哈希表,内存开销大 | 快速键值查找 |
| 集合 | 哈希表,只存储键 | 去重和集合运算 |
6.3 实际项目选型建议
- 数据检索:优先考虑字典或集合,它们的O(1)查找时间远快于列表的O(n)
- 数据去重:集合是天然的去重工具,比手动检查列表高效得多
- 数据排序:如果需要保持插入顺序,Python 3.7+的字典或OrderedDict是更好的选择
- 函数返回多个值:使用元组而非列表,既安全又高效
- 配置数据:不可变的元组比列表更适合存储配置常量
7. 容器使用中的常见陷阱与解决方案
7.1 列表在循环中修改的问题
在遍历列表时直接修改它会导致意外结果:
python复制# 错误做法 - 会跳过某些元素
numbers = [1, 2, 3, 4]
for num in numbers:
if num % 2 == 0:
numbers.remove(num)
print(numbers) # 可能是 [1, 3] 也可能是 [1, 3, 4]
# 正确做法1 - 遍历副本
numbers = [1, 2, 3, 4]
for num in numbers[:]:
if num % 2 == 0:
numbers.remove(num)
print(numbers) # [1, 3]
# 正确做法2 - 列表推导式
numbers = [1, 2, 3, 4]
numbers = [num for num in numbers if num % 2 != 0]
print(numbers) # [1, 3]
7.2 字典键的可哈希性要求
不是所有Python对象都可以作为字典键:
python复制# 有效的键
valid_keys = [123, "hello", (1, 2), frozenset([1, 2])]
# 无效的键
invalid_keys = [[1, 2], {"a": 1}, set([1, 2])]
7.3 默认参数的陷阱
容器作为函数默认参数时有一个常见陷阱:
python复制# 错误做法 - 所有调用共享同一个列表
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] 不是预期的[2]
# 正确做法 - 使用None作为默认值
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
7.4 浅拷贝与深拷贝的实际影响
理解拷贝的深浅对避免bug至关重要:
python复制# 嵌套结构的修改问题
original = [[1, 2], [3, 4]]
shallow_copy = original.copy()
shallow_copy[0][0] = 99
print(original) # [[99, 2], [3, 4]] 原数据被意外修改
# 使用深拷贝避免这个问题
import copy
deep_copy = copy.deepcopy(original)
deep_copy[0][0] = 100
print(original) # [[99, 2], [3, 4]] 原数据不受影响
8. 性能优化实战技巧
8.1 使用生成器表达式替代列表
对于只需要迭代一次的数据,使用生成器可以节省内存:
python复制# 列表推导式 - 立即计算所有结果
sum([x**2 for x in range(1000000)]) # 占用大量内存
# 生成器表达式 - 惰性计算
sum(x**2 for x in range(1000000)) # 内存高效
8.2 利用集合快速去重
集合去重比手动检查快得多:
python复制# 慢速去重
def slow_unique(items):
result = []
for item in items:
if item not in result:
result.append(item)
return result
# 快速去重
def fast_unique(items):
return list(set(items))
# 保持顺序的去重
def ordered_unique(items):
seen = set()
return [x for x in items if not (x in seen or seen.add(x))]
8.3 字典合并的多种方式
Python 3.9+提供了多种字典合并方式:
python复制d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
# 传统方法
merged = {**d1, **d2} # {'a': 1, 'b': 3, 'c': 4}
# Python 3.9+方法
merged = d1 | d2 # 同上
# 就地更新
d1.update(d2) # d1变为合并后的字典
8.4 使用bisect管理有序列表
对于需要保持有序的大型列表,bisect模块非常高效:
python复制import bisect
data = []
for num in [3, 1, 4, 1, 5, 9, 2, 6]:
bisect.insort(data, num)
print(data) # [1, 1, 2, 3, 4, 5, 6, 9]
# 快速查找
index = bisect.bisect_left(data, 4)
print(index) # 3
9. 容器在数据科学中的特殊应用
9.1 使用字典计数
字典是计数的天然工具:
python复制from collections import defaultdict, Counter
# 手动计数
counts = {}
for item in data:
counts[item] = counts.get(item, 0) + 1
# 使用defaultdict
counts = defaultdict(int)
for item in data:
counts[item] += 1
# 最简单的方法 - Counter
counts = Counter(data)
print(counts.most_common(3)) # 最常见的3个元素
9.2 使用集合进行数据清洗
集合运算非常适合数据清洗:
python复制# 找出两个数据源的交集和差异
db_users = set(get_users_from_db())
api_users = set(get_users_from_api())
# 只在DB中存在的用户
db_only = db_users - api_users
# 只在API中存在的用户
api_only = api_users - db_users
# 两边都存在的用户
common_users = db_users & api_users
9.3 使用元组作为pandas索引
在pandas中,元组常被用作多层索引:
python复制import pandas as pd
index = [("A", 1), ("A", 2), ("B", 1), ("B", 2)]
values = [10, 20, 30, 40]
s = pd.Series(values, index=pd.MultiIndex.from_tuples(index))
print(s)
"""
A 1 10
2 20
B 1 30
2 40
dtype: int64
"""
10. 容器与Python特殊方法
10.1 实现容器协议的魔术方法
自定义类可以通过实现特殊方法使其行为像内置容器:
python复制class ShoppingCart:
def __init__(self):
self.items = []
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __contains__(self, item):
return item in self.items
def add(self, item):
self.items.append(item)
cart = ShoppingCart()
cart.add("apple")
cart.add("banana")
print(len(cart)) # 2
print("apple" in cart) # True
print(cart[1]) # "banana"
10.2 使用__slots__优化内存
对于创建大量实例的类,__slots__可以显著减少内存使用:
python复制class Point:
__slots__ = ('x', 'y') # 只允许这两个属性
def __init__(self, x, y):
self.x = x
self.y = y
# 相比普通类,使用__slots__的类实例内存占用更小
# 但不能动态添加新属性
10.3 上下文管理器与容器
容器可以与上下文管理器结合,实现资源管理:
python复制from contextlib import contextmanager
@contextmanager
def temporary_mapping(mapping, key, value):
"""临时添加键值对,退出时恢复"""
original = mapping.get(key, None)
mapping[key] = value
try:
yield
finally:
if original is not None:
mapping[key] = original
else:
del mapping[key]
data = {"a": 1}
with temporary_mapping(data, "b", 2):
print(data) # {'a': 1, 'b': 2}
print(data) # {'a': 1} 自动恢复
11. 容器在多线程环境中的使用
11.1 线程安全注意事项
Python的基本容器操作是原子性的,但复合操作不是:
python复制# 线程不安全的操作
if key in dictionary:
value = dictionary[key] # 这两步之间可能被其他线程打断
# 线程安全的替代方案
try:
value = dictionary[key]
except KeyError:
pass
11.2 使用Queue进行线程间通信
queue模块提供了线程安全的容器:
python复制from queue import Queue
import threading
def worker(q):
while True:
item = q.get()
if item is None:
break
print(f"Processing {item}")
q.task_done()
q = Queue()
threads = []
for i in range(4):
t = threading.Thread(target=worker, args=(q,))
t.start()
threads.append(t)
for item in range(10):
q.put(item)
q.join() # 等待所有任务完成
for i in range(4):
q.put(None) # 停止信号
for t in threads:
t.join()
12. 容器与函数式编程
12.1 使用map/filter/reduce
函数式编程风格可以简化容器操作:
python复制from functools import reduce
numbers = [1, 2, 3, 4, 5]
# 平方每个元素
squares = list(map(lambda x: x**2, numbers))
# 过滤偶数
evens = list(filter(lambda x: x % 2 == 0, numbers))
# 计算乘积
product = reduce(lambda x, y: x * y, numbers, 1)
12.2 使用itertools处理大型容器
itertools模块提供了高效处理大型容器的工具:
python复制from itertools import islice, chain, groupby
# 分块处理大型列表
def chunked(iterable, size):
it = iter(iterable)
return iter(lambda: list(islice(it, size)), [])
# 合并多个容器
combined = chain.from_iterable([[1, 2], [3, 4], [5]])
# 分组操作
data = sorted([("a", 1), ("b", 2), ("a", 3)], key=lambda x: x[0])
for key, group in groupby(data, lambda x: x[0]):
print(key, list(group))
13. 容器在算法中的应用
13.1 使用字典实现图
字典非常适合表示图结构:
python复制graph = {
"A": ["B", "C"],
"B": ["A", "D", "E"],
"C": ["A", "F"],
"D": ["B"],
"E": ["B", "F"],
"F": ["C", "E"]
}
def bfs(graph, start):
visited = set()
queue = [start]
while queue:
vertex = queue.pop(0)
if vertex not in visited:
visited.add(vertex)
queue.extend(set(graph[vertex]) - visited)
return visited
13.2 使用集合实现布隆过滤器
集合可以模拟布隆过滤器的基本功能:
python复制class SimpleBloomFilter:
def __init__(self, size=1000):
self.size = size
self.storage = set()
def _hash(self, item):
return hash(item) % self.size
def add(self, item):
self.storage.add(self._hash(item))
def __contains__(self, item):
return self._hash(item) in self.storage
bf = SimpleBloomFilter()
bf.add("hello")
print("hello" in bf) # True
print("world" in bf) # False (可能有误判)
14. 容器与元编程
14.1 动态创建容器类型
type()函数可以动态创建容器类:
python复制def __len__(self):
return len(self._data)
def __getitem__(self, index):
return self._data[index]
CustomList = type(
"CustomList",
(object,),
{
"__init__": lambda self, data: setattr(self, "_data", list(data)),
"__len__": __len__,
"__getitem__": __getitem__,
"append": lambda self, item: self._data.append(item)
}
)
lst = CustomList([1, 2, 3])
print(len(lst)) # 3
print(lst[1]) # 2
lst.append(4)
14.2 使用collections.abc抽象基类
创建自定义容器时,继承抽象基类可以确保接口一致性:
python复制from collections.abc import MutableSequence
class CustomList(MutableSequence):
def __init__(self, data=None):
self._data = list(data) if data else []
def __len__(self):
return len(self._data)
def __getitem__(self, index):
return self._data[index]
def __setitem__(self, index, value):
self._data[index] = value
def __delitem__(self, index):
del self._data[index]
def insert(self, index, value):
self._data.insert(index, value)
def __str__(self):
return str(self._data)
lst = CustomList([1, 2, 3])
lst.append(4) # 继承自MutableSequence的方法
print(lst) # [1, 2, 3, 4]
15. 容器性能测试与调优
15.1 使用timeit测量操作速度
Python的timeit模块可以精确测量容器操作性能:
python复制from timeit import timeit
# 比较列表和集合的成员测试速度
list_time = timeit("1000000 in lst", setup="lst = list(range(1000000))", number=100)
set_time = timeit("1000000 in s", setup="s = set(range(1000000))", number=100)
print(f"List: {list_time:.6f} seconds")
print(f"Set: {set_time:.6f} seconds")
15.2 使用memory_profiler测量内存使用
memory_profiler可以帮助分析容器的内存占用:
python复制from memory_profiler import profile
@profile
def create_large_containers():
big_list = list(range(1000000))
big_dict = {i: i for i in range(1000000)}
big_set = set(range(1000000))
return big_list, big_dict, big_set
_ = create_large_containers()
15.3 性能优化实战案例
优化一个统计单词频率的函数:
python复制# 原始版本
def word_count(text):
words = text.split()
count = {}
for word in words:
if word in count:
count[word] += 1
else:
count[word] = 1
return count
# 优化版本1 - 使用defaultdict
from collections import defaultdict
def word_count_v1(text):
words = text.split()
count = defaultdict(int)
for word in words:
count[word] += 1
return dict(count)
# 优化版本2 - 使用Counter
from collections import Counter
def word_count_v2(text):
return dict(Counter(text.split()))
# 测试性能
text = "hello world hello python hello coding world" * 10000
print(timeit("word_count(text)", globals=globals(), number=10))
print(timeit("word_count_v1(text)", globals=globals(), number=10))
print(timeit("word_count_v2(text)", globals=globals(), number=10))
16. 容器与Python新特性
16.1 Python 3.9+的字典合并操作
Python 3.9引入了更简洁的字典合并语法:
python复制# 传统方法
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
merged = {**d1, **d2}
# Python 3.9+方法
merged = d1 | d2 # 更简洁
d1 |= d2 # 就地更新
16.2 类型注解与容器
Python的类型提示系统对容器有很好的支持:
python复制from typing import Dict, List, Set, Tuple, Optional
def process_data(
items: List[str],
counts: Dict[str, int],
flags: Set[int],
point: Tuple[float, float],
extra: Optional[List[int]] = None
) -> Dict[str, float]:
"""处理多种容器类型的数据"""
# 函数实现...
return {"result": 1.0}
16.3 数据类(dataclass)作为高级容器
Python 3.7引入的dataclasses可以看作更强大的容器:
python复制from dataclasses import dataclass, field
from typing import List
@dataclass
class InventoryItem:
name: str
unit_price: float
quantity: int = 0
tags: List[str] = field(default_factory=list)
item = InventoryItem("widget", 9.99, 10, ["sale", "new"])
print(item) # 自动生成__repr__
17. 容器在Web开发中的应用
17.1 使用字典处理JSON数据
字典是处理JSON数据的自然选择:
python复制import json
# 从JSON字符串创建字典
data = json.loads('{"name": "Alice", "age": 30}')
# 从字典生成JSON
user = {"name": "Bob", "scores": [85, 90, 78]}
json_str = json.dumps(user, indent=2)
17.2 使用列表处理分页数据
列表切片非常适合实现分页功能:
python复制def paginate(items, page, per_page):
start = (page - 1) * per_page
end = start + per_page
return items[start:end]
data = list(range(100)) # 模拟100条数据
print(paginate(data, page=2, per_page=10)) # [10, 11, ..., 19]
17.3 使用集合管理用户会话
集合可以高效管理活跃用户会话:
python复制active_sessions = set()
def login(user_id):
active_sessions.add(user_id)
def logout(user_id):
active_sessions.discard(user_id)
def is_active(user_id):
return user_id in active_sessions
18. 容器在系统编程中的应用
18.1 使用字典管理文件类型
字典可以优雅地映射文件扩展名到处理函数:
python复制file_handlers = {
".txt": handle_text_file,
".csv": handle_csv_file,
".json": handle_json_file,
".xml": handle_xml_file
}
def process_file(filename):
ext = filename[filename.rfind("."):].lower()
handler = file_handlers.get(ext, handle_unknown_file)
return handler(filename)
18.2 使用队列处理进程间通信
multiprocessing.Queue是进程安全的容器:
python复制from multiprocessing import Process, Queue
def worker(q):
while True:
item = q.get()
if item is None:
break
print(f"Processing {item}")
q = Queue()
p = Process(target=worker, args=(q,))
p.start()
for item in range(10):
q.put(item)
q.put(None) # 结束信号
p.join()
18.3 使用namedtuple处理系统信息
namedtuple适合表示系统信息:
python复制from collections import namedtuple
import os
DiskUsage = namedtuple("DiskUsage", ["total", "used", "free"])
def get_disk_usage(path):
stat = os.statvfs(path)
total = stat.f_blocks * stat.f_frsize
free = stat.f_bfree * stat.f_frsize
return DiskUsage(total, total - free, free)
19. 容器在GUI开发中的应用
19.1 使用列表管理GUI组件
列表可以方便地管理一组相关组件:
python复制import tkinter as tk
root = tk.Tk()
entries = []
for i in range(5):
entry = tk.Entry(root)
entry.pack()
entries.append(entry)
def get_values():
return [e.get() for e in entries]
tk.Button(root, text="Get Values", command=get_values).pack()
root.mainloop()
19.2 使用字典管理界面状态
字典适合存储和管理界面状态:
python复制class Application:
def __init__(self):
self.state = {
"logged_in": False,
"current_user": None,
"preferences": {},
"open_windows": []
}
def login(self, username):
self.state["logged_in"] = True
self.state["current_user"] = username
def add_window(self, window):
self.state["open_windows"].append(window)
20. 容器在游戏开发中的应用
20.1 使用列表表示游戏地图
二维列表可以表示简单的游戏地图:
python复制# 简单的2D游戏地图
game_map = [
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 2, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
]
# 0=空地, 1=墙, 2=玩家
def draw_map(map_data):
for row in map_data:
print("".join(str(cell) for cell in row))
20.2 使用集合管理游戏实体
集合适合管理需要快速查找的游戏实体:
python复制class Game:
def __init__(self):
self.entities = set()
self.collidable = set()
self.renderable = set()
def add_entity(self, entity):
self.entities.add(entity)
if hasattr(entity, "collide"):
self.collidable.add(entity)
if hasattr(entity, "render"):
self.renderable.add(entity)
def check_collisions(self):
for entity in self.collidable:
# 简化的碰撞检测
if entity.position in [e.position for e in self.collidable if e != entity]:
entity.on_collision()
21. 容器在机器学习中的应用
21.1 使用字典存储特征映射
字典适合存储类别特征到数值的映射:
python复制# 类别特征编码
categories = ["red", "green", "blue", "green", "red"]
category_map = {v: i for i, v in enumerate(set(categories))}
encoded = [category_map[c] for c in categories]
print(encoded) # 如 [0, 1, 2, 1, 0]
21.2 使用列表批处理数据
列表切片可以实现简单的批处理:
python复制def batch_generator(data, batch_size):
for i in range(0, len(data), batch_size):
yield data[i:i + batch_size]
data = list(range(100))
for batch in batch_generator(data, 10):
print(batch) # 每次输出10个元素的批次