FileIO 对象和 open(filename, mode) 返回的对象的区别

Difference between FileIO object and object returned by open(filename, mode)

Python 有几个 io 基础 类 包括

IOBase
RawIOBase
BufferedIOBase
TextIOBase

以及几个派生的io 类:

FileIO
BytesIO

现在,当我创建一个 BytesIO 对象时,mro 是:

[<class '_io.BytesIO'>, <class '_io._BufferedIOBase'>, <class '_io._IOBase'>, <class 'object'>]

当我创建一个 FileIO 对象时,mro 是:

[<class '_io.FileIO'>, <class '_io._RawIOBase'>, <class '_io._IOBase'>, <class 'object'>]

这很简单。

但是,当我打开一个二进制 文件 以使用内置打开进行写入时,我得到了 mro:

[<class '_io.BufferedWriter'>, <class '_io._BufferedIOBase'>, <class '_io._IOBase'>, <class 'object'>]

根据最小意外原则,打开 文件 的命令不是应该 return 一个 FileIO 对象吗? 我刚刚写了一个接受 BytesIOfile 的方法,我偶然发现了我的 if isinstance(io.FileIO) ... 子句。 FileIO 对象和由 open return 编辑的对象有什么区别?

主要区别在于 FileIO 继承自 RawIOBase class,后者提供 low-level 对 OS-level API 的访问,但是open 函数 return 一个 BufferedIOBase 继承者,更适合一般情况(我认为))。作为副作用 FileIO 可以使用 OS-level 文件描述符作为名称(open 仅允许 path-like)。所以 FileIO 提供了更灵活的 API 来处理二进制文件或流(例如减少内存使用等),open - 没有。有关差异的更多信息 here.

打个比方——open一般是锉刀,FileIO是外科医生的手术刀。

所以对于你的问题,可能 isinstance 不是正确的选择,可能最好使用“duck-typing”方法并检查对象是否有必要的方法(或使用另一个输入 isinstance 进行检查,例如 IOBase 是否满足您的需求)。您也可以使用对象的readable()seekable()writable()方法来检查必要条件