【编程之路】按指定大小合并数据块
按指定大小合并数据块
- 1.函数 combine(source, maxsize) 的功能
- 2.文件操作部分
- 3.示例流程
- 4.典型应用场景
- 5.注意事项
- 6.改进建议
🚀 本文讨论的代码段来自《Python Cookbook》的《2.14.合并拼接字符串》。
针对下面这段代码,我们一起来分析一下
def combine(source, maxsize):
parts = []
size = 0
for part in source:
parts.append(part)
size += len(part)
if size > maxsize:
yield ''.join(parts)
parts = []
size = 0
yield ''.join(parts)
# 结合文件操作
with open('filename', 'w') as f:
for part in combine(sample(), 32768):
f.write(part)
这段代码定义了一个生成器函数 combine(),用于将多个小块数据(如字符串或字节)按指定大小(maxsize)合并成较大的块,然后通过文件操作写入文件。下面逐步解析其逻辑和用途:
1.函数 combine(source, maxsize) 的功能
- 输入参数:
source:一个可迭代对象(如列表、生成器),提供多个数据块(如字符串或字节)。maxsize:合并后的最大尺寸阈值(如 32768 32768 32768 字节)。
- 输出:生成合并后的较大块(通过
yield逐步返回)。 - 核心逻辑:
- 初始化空列表
parts和计数器size。 - 遍历
source中的每个part:- 将
part加入parts列表,并累加其长度到size。 - 如果
size超过maxsize,则合并parts中的所有块(''.join(parts)),通过yield返回合并结果,并清空parts和size。
- 将
- 遍历结束后,返回剩余的未合并的块(
yield ''.join(parts))。
- 初始化空列表
- 关键点:
- 这是一个生成器函数(使用
yield),不会一次性返回所有结果,而是按需生成。 - 合并的触发条件是
size > maxsize,因此实际返回的块大小可能略大于maxsize(取决于最后一个part的大小)。
- 这是一个生成器函数(使用
2.文件操作部分
with open('filename', 'w') as f:
for part in combine(sample(), 32768):
f.write(part)
- 作用:将
combine()生成的合并块逐块写入文件。 - 细节:
sample():假设是一个生成数据块的函数(如返回字符串列表或生成器)。combine(sample(), 32768):将sample()的数据按每块最大 32768 32768 32768 字节合并。f.write(part):将合并后的块写入文件。
3.示例流程
假设 sample() 返回以下字符串列表,且 maxsize=10:
def sample():
return ["Hello", " ", "World", "!", " How", " are", " you?"]
# 调用 combine(sample(), 10)
执行过程:
- 第一次合并:
"Hello" + " " + "World"→ 长度5+1+5=11 > 10→ 返回"Hello World"。 - 第二次合并:
"!" + " How" + " are"→ 长度1+4+4=9 ≤ 10,继续。 - 第三次合并:加入
" you?"→ 长度9+5=14 > 10→ 返回"! How are"。 - 最后剩余
" you?"→ 返回" you?"。
最终写入文件的内容:
Hello World! How are you?
4.典型应用场景
- 大文件分块处理:例如从网络或数据库读取大量小数据块时,合并为较大的块后再写入文件,减少 I/O 操作次数。
- 内存优化:避免一次性加载所有数据到内存(适合处理大型数据流)。
5.注意事项
- 块大小的准确性:
- 实际合并后的块大小可能超过
maxsize(因为当前part加入后才会检查条件)。 - 如果需要严格不超过
maxsize,需在加入part前检查size + len(part)。
- 实际合并后的块大小可能超过
- 数据边界问题:如果
part是二进制数据(如字节),需用b''.join(parts)。 - 生成器的惰性:
combine()是惰性求值的,适合处理流式数据(如从网络逐块读取)。
6.改进建议
若需严格限制块大小,可调整逻辑如下:
def combine_strict(source, maxsize):
parts = []
size = 0
for part in source:
if size + len(part) > maxsize:
if parts: # 避免空块
yield ''.join(parts)
parts = []
size = 0
parts.append(part)
size += len(part)
if parts:
yield ''.join(parts)
这样能确保每个块严格满足 size <= maxsize。
