如何检查一个对象是否是'file'实例?
以前在Python(2.6)中,我们可以这样询问:
isinstance(f, file)
但是在Python 3.0中,file
这个东西被去掉了。
那么现在检查一个变量是否是文件的正确方法是什么呢?更新文档里没有提到这个……
4 个回答
通常情况下,你不需要去检查一个对象的类型,可以使用“鸭子类型”来处理。也就是说,直接调用 f.read()
,如果出现错误,就让错误继续传播下去——这可能是你代码中的一个bug,或者是调用代码中的bug。例如,如果你给 json.load()
一个没有 read
属性的对象,它会抛出 AttributeError
错误。
如果你需要区分几种可以接受的输入类型,可以使用 hasattr/getattr
来帮助你:
def read(file_or_filename):
readfile = getattr(file_or_filename, 'read', None)
if readfile is not None: # got file
return readfile()
with open(file_or_filename) as file: # got filename
return file.read()
如果你想支持一种情况,即 file_of_filename
可能有一个 read
属性,但这个属性的值是 None
,那么你可以在 file_or_filename.read
上使用 try/except
,注意:这里不需要加括号,因为并没有实际调用——例如,ElementTree._get_writer()
。
如果你想检查某些特定的保证,比如只进行一次系统调用(io.RawIOBase.read(n)
,当 n > 0 时),或者没有短写(io.BufferedIOBase.write()
),或者读写方法是否接受文本数据(io.TextIOBase
),那么你可以使用 isinstance()
函数,结合 在 io
模块中定义的 ABCs,例如,看看 saxutils._gettextwriter()
是怎么实现的。
def read_a_file(f)
try:
contents = f.read()
except AttributeError:
# f is not a file
根据你计划使用的方法来替换 read
。如果你预计大约98%的情况下会处理一个类似文件的对象,这样做是最优的。如果你认为会有超过2%的情况处理到非文件对象,那么正确的做法是:
def read_a_file(f):
if hasattr(f, 'read'):
contents = f.read()
else:
# f is not a file
这正是你如果有一个 file
类可以测试时会做的事情。(顺便说一下,我在2.6版本中也有 file
)请注意,这段代码在3.x版本中也能正常工作。