实现完整Python文件接口需要哪些最小文件方法子集?

9 投票
3 回答
1669 浏览
提问于 2025-04-16 13:52

Python有一个很棒的collections模块,它提供了一些工具,让你可以用很少的方法来实现一个完整的dict(字典)。那么,Python中有没有类似的东西可以用来处理file(文件)接口呢?如果没有,你会推荐哪些最基本的方法来实现一个像文件一样的对象,以便进行鸭子类型(duck typing)?

而且,如何处理那些想要在with语句中使用你的文件对象的情况,就像使用普通文件一样,或者想要遍历它(就像普通文件那样),或者想要调用readlinereadlines并让它做一些聪明而有用的事情(就像普通文件那样)?你需要自己实现所有这些功能吗?还是有更好的选择?

我知道我可以手动实现每一个功能。但是,collections接口让我只需要实现__len____iter____setitem____getitem__就可以实现一个dict。这样我就可以免费获得poppopitemclearupdatesetdefault__contains__keysitemsvaluesget__eq____ne__等方法。只要我实现了__dict__的最小接口,就能获得完整的dict接口,所有额外的方法都是基于这个最小接口实现的。

同样,我也想知道,要实现完整的文件接口,我需要实现哪些最基本的接口。如果我只实现readwriteclose,是否就能获得__enter____exit__readlinereadlines__iter__next这些功能,还是说每次想要完整的file接口时,我都得手动实现所有功能?

3 个回答

2

你其实已经部分回答了这个问题。虽然没有一套“特殊”的方法是必须要实现的来让一个类像文件一样工作,但你只需要提供一些通常和文件相关的方法就可以了。鸭子类型(Duck typing)会处理其他的事情。

你只需要一个 read 方法和/或一个 write 方法(这取决于你想让这个对象是可读的还是可写的),这些方法的行为要和普通的文件对象一样。你可以查看一下 Python 文件对象 的参考文档,看看文件对象有哪些方法。基本上,你实现的方法越多,你的类就能在更多需要文件的地方使用。(比如,如果你实现了 seek 方法,那么它就可以在任何需要对文件进行定位的函数中使用。)需要注意的是,这里是一个连续的过程,并没有绝对的“支持文件协议”或“不支持文件协议”。实际上,没有办法让你的类在所有支持类文件对象的地方都能100%工作,因为有些代码会访问真实 file 类型的低级细节,而你的类在这些地方就无法使用。

总之,任何实现了 readwrite 方法的类在大多数需要“类文件对象”的情况下都能正常工作。

(注意,像 __getitem__ 这样的特殊方法名对于字典来说并不是真的特殊,除了它们被像 [key] 这样的特殊语法使用——这就是为什么字典有特殊方法名而文件没有的原因。)

2

我建议你看看 io.IOBase[1] 和 io.RawIOBase,这样可以确保你的代码在 2.6 版本以上也能兼容。这样做可以帮助你顺利过渡到 3.x 版本,因为 io 模块实现了 3.x 的文件接口。

[1] http://docs.python.org/library/io.html#i-o-base-classes

3

使用 with 语句需要一个上下文管理器:

http://docs.python.org/library/stdtypes.html#typecontextmanager

文件类型的定义很完整:

http://docs.python.org/library/stdtypes.html#file-objects

看起来挺简单的。

文档中列出了文件和上下文管理器的方法和属性。你需要实现这些。

你还需要什么更多的信息呢?

http://docs.python.org/library/contextlib.html?highlight=context%20manager

如果你想让所有的方法都能正常工作,你就得实现所有的方法。和集合不同,文件没有抽象基类。

撰写回答