【问题标题】:file name vs file object as a function argument文件名与文件对象作为函数参数
【发布时间】:2012-09-16 14:28:20
【问题描述】:

如果函数将文本文件的名称作为输入,我可以将其重构为使用文件对象(我称之为“流”;有更好的词吗?)。优点是显而易见的 - 将流作为参数的函数是:

  • 编写单元测试要容易得多,因为我不需要仅为测试创建临时文件
  • 更灵活,因为我可以在以某种方式已经在变量中包含文件内容的情况下使用它

流有什么缺点吗?或者我应该总是将函数从文件名参数重构为流参数(当然,假设文件是​​纯文本的)?

【问题讨论】:

    标签: python unit-testing python-3.x arguments software-design


    【解决方案1】:

    ... 以下是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 略有不同。流可能是无限的,而文件通常不是(除非某些设备像文件一样被映射)。处理时的重要区别是,您永远不能一次将流读入内存。你必须分块处理它。

    【讨论】:

    • 我在标准库中寻找一个参考实现。感谢sn-p,它确实节省了时间。如果可以的话,我会再给块警告+1。
    【解决方案2】:

    python 标准库中有许多函数可以同时接受——作为文件名或打开文件对象的字符串(我假设这就是您所说的“流”)。创建一个装饰器真的不难,你可以用它来让你的函数接受任何一个。

    使用“流”的一个严重缺点是您将它传递给您的函数,然后您的函数从中读取——有效地改变了它的状态。根据您的程序,如果有必要,恢复该状态可能会很麻烦。 (例如,您可能需要使用f.tell()f.seek() 乱扔代码。)

    【讨论】:

    • 是的,当我说“流”时,我的意思是“打开文件对象”。难道不能写一个装饰器来保存和恢复流状态吗?
    • 难道没有办法创建一个廉价的流副本,使得副本拥有自己的“指针”,而原始流的“指针”保持不变?这甚至比保存/恢复状态方法更干净。
    • 所以文件名 vs 文件对象感觉有点像可迭代 vs 迭代器。
    • @max -- 我想是相似的。
    • 我不能为别人说话,但我通常想要改变流状态的功能。例如。我希望我的(假设的)“parse_header”函数将文件指针留在标题的末尾,以便随后的“read_item”可以从文件中的适当点开始读取。
    猜你喜欢
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    相关资源
    最近更新 更多