本文讨论的代码段来自《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
)合并成较大的块,然后通过文件操作写入文件。下面逐步解析其逻辑和用途:
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
的大小)。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)
:将合并后的块写入文件。假设 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?
maxsize
(因为当前 part
加入后才会检查条件)。maxsize
,需在加入 part
前检查 size + len(part)
。part
是二进制数据(如字节),需用 b''.join(parts)
。combine()
是惰性求值的,适合处理流式数据(如从网络逐块读取)。若需严格限制块大小,可调整逻辑如下:
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
。