如果一个函数将文本文件的名称作为输入,我可以将其重构为采用文件对象(我称之为“流”;有更好的词吗?)。优点是显而易见的 - 将流作为参数的函数是:
- 编写单元测试要容易得多,因为我不需要仅为测试创建临时文件
- 更灵活,因为我可以在我以某种方式已经在变量中拥有文件内容的情况下使用它
流有什么缺点吗?或者我应该总是将函数从文件名参数重构为流参数(当然,假设文件是纯文本的)?
如果一个函数将文本文件的名称作为输入,我可以将其重构为采用文件对象(我称之为“流”;有更好的词吗?)。优点是显而易见的 - 将流作为参数的函数是:
流有什么缺点吗?或者我应该总是将函数从文件名参数重构为流参数(当然,假设文件是纯文本的)?
...这是xml.etree.ElementTree
模块实现该parse
功能的方式:
def parse(self, source, parser=None):
close_source = False
if not hasattr(source, "read"):
source = open(source, "rb")
close_source = True
...
由于文件名是一个字符串,它没有read()
方法(这里检查该名称的任何属性);但是,打开的文件有它。这四行代码使其余代码通用。唯一的麻烦是您必须记住是否关闭文件对象(这里命名为source
)。如果它在open
里面,那么它必须被关闭。否则,不得关闭。
实际上,文件与 sreams 略有不同。流可能是无限的,而文件通常不是(除非某些设备像文件一样被映射)。处理时的重要区别是,您永远不能一次将流读入内存。您必须按块处理它。
python 标准库中有许多函数可以同时接受——作为文件名或打开文件对象的字符串(我假设这就是你所说的“流”)。创建一个装饰器真的不难,你可以用它来让你的函数接受任何一个。
使用“流”的一个严重缺点是你将它传递给你的函数,然后你的函数从中读取——有效地改变它的状态。根据您的程序,如果有必要,恢复该状态可能会很麻烦。(例如,您可能需要乱扔代码,f.tell()
然后f.seek()
.)