Python 作为函数参数的文件名与文件对象
如果一个函数以文本文件的名称作为输入,我可以将其重构为一个file对象(我称之为“stream”;还有更好的词吗?)。优点显而易见-将流作为参数的函数是:Python 作为函数参数的文件名与文件对象,python,unit-testing,python-3.x,arguments,software-design,Python,Unit Testing,Python 3.x,Arguments,Software Design,如果一个函数以文本文件的名称作为输入,我可以将其重构为一个file对象(我称之为“stream”;还有更好的词吗?)。优点显而易见-将流作为参数的函数是: 编写单元测试要容易得多,因为我不需要为测试创建临时文件 更灵活,因为我可以在变量中已经包含文件内容的情况下使用它 溪流有什么缺点吗?或者我应该始终将函数从文件名参数重构为流参数(当然,假设文件仅为文本)?python标准库中有许多函数同时接受这两种参数——字符串是文件名或打开的文件对象(我假设这就是您所指的“流”)。创建一个装饰器并不难,
- 编写单元测试要容易得多,因为我不需要为测试创建临时文件
- 更灵活,因为我可以在变量中已经包含文件内容的情况下使用它
溪流有什么缺点吗?或者我应该始终将函数从文件名参数重构为流参数(当然,假设文件仅为文本)?python标准库中有许多函数同时接受这两种参数——字符串是文件名或打开的文件对象(我假设这就是您所指的“流”)。创建一个装饰器并不难,您可以使用它使您的函数接受其中任何一个
使用“流”的一个严重缺点是,将它传递给函数,然后函数从中读取——有效地改变了它的状态。根据您的程序,如果有必要,恢复该状态可能会很混乱。(例如,您可能需要在代码中乱扔
f.tell()
,然后f.seek()
)。。。以下是xml.etree.ElementTree
模块如何实现该功能:
def parse(self, source, parser=None):
close_source = False
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
...
由于filename是一个字符串,因此它没有read()
方法(此处选中该名称的任何属性);但是,打开的文件有它。这四行代码使其余代码变得通用。唯一复杂的是,您必须记住是否关闭文件对象(此处命名为source
)。如果它是打开的
内部,则必须将其关闭。否则,不得将其关闭
实际上,文件与sream略有不同。流可能是无限的,而文件通常不是无限的(除非某些设备被映射为文件)。处理时的重要区别在于,您永远无法将流一次读入内存。您必须按块处理它。是的,当我说“流”时,我的意思是“打开文件对象”。难道不可能编写一个保存和恢复流状态的装饰程序吗?难道没有一种方法可以创建一个廉价的流副本,这样副本就拥有自己的“指针”,而原始流的“指针”就保持不变吗?这比“保存/还原状态”方法更简洁。因此,“文件名”与“文件对象”感觉有点像“iterable”与“迭代器”。@max--我想这是类似的。我不能代表其他人说话,但我通常希望函数更改流的状态。例如,我希望我的(假设的)“parse_header”函数将文件指针保留在头的末尾,这样下面的“read_item”就可以从文件中的适当点开始读取。我正在stdlib中寻找关于这一点的参考实现。谢谢你的片段,它真的节省了时间。如果可以的话,我会给另外一个+1作为块的警告。