类文件对象是Python中的对象,其行为类似于真实文件,例如具有read()和write方法(),但具有不同的实现.它是鸭子打字概念的实现.
在文件预期的任何地方允许类似文件的对象被认为是一种好的做法,例如可以使用StringIO或Socket对象来代替真实文件.所以执行这样的检查是不好的:
if not isinstance(fp, file):
raise something
Run Code Online (Sandbox Code Playgroud)
检查对象(例如方法的参数)是否"类似文件"的最佳方法是什么?
aba*_*ert 56
对于3.1+,以下之一:
isinstance(something, io.TextIOBase)
isinstance(something, io.BufferedIOBase)
isinstance(something, io.RawIOBase)
isinstance(something, io.IOBase)
Run Code Online (Sandbox Code Playgroud)
对于2.x,"类似文件的对象"太过模糊,无法检查,但是您正在处理的任何函数的文档都希望能够告诉您实际需要的内容; 如果没有,请阅读代码.
正如其他答案所指出的那样,首先要问的是你究竟要检查的是什么.通常,EAFP足够,而且更具惯用性.
词汇说"类文件对象"是"文件对象",同义词这最终意味着它是三者之一的一个实例抽象基类中所定义的io
模块,其本身的所有子类IOBase
.因此,检查的方式完全如上所示.
(但是,检查IOBase
不是很有用.你能想象一种情况,你需要区分一个实际的文件类似于read(size)
一个名为read
不像文件的单参数函数,而不需要区分文本文件和原始文件二进制文件?所以,实际上,你几乎总是要检查,例如,"是一个文本文件对象",而不是"是一个类似文件的对象".)
对于2.x,虽然io
模块自2.6+以来就存在,但内置文件对象不是io
类的实例,stdlib中的任何类文件对象都不是,并且大多数类似于第三方文件的对象都没有很可能会遇到."文件类对象"的含义没有官方定义; 它只是"类似于内置文件对象的东西",不同的功能意味着"喜欢"不同的东西.这些功能应记录它们的含义; 如果他们不这样做,你必须看看代码.
但是,最常见的含义是"has read(size)
","has read()
"或"是一个可迭代的字符串",但是一些旧的库可能期望readline
而不是其中一个,一些库喜欢close()
你给它们的文件,有些人会期望如果fileno
存在然后其他功能可用,等等.write(buf)
(尽管在该方向上有很多选项).
Ten*_*she 47
除非您有特殊要求,否则在您的代码中进行这样的检查通常不是一种好的做法.
在Python中,键入是动态的,为什么你觉得需要检查对象是否像文件一样,而不是仅仅使用它就好像它是一个文件并处理结果错误?
你可以做的任何检查都会在运行时发生,所以做一些类似的事情if not hasattr(fp, 'read')
并提出一些异常只比调用fp.read()
和处理结果属性错误(如果该方法不存在)提供更多的实用工具.
Sco*_*ths 45
正如其他人所说,你通常应该避免这种检查.一个例外是当对象可能合法地是不同的类型,并且您希望根据类型而有不同的行为.EAFP方法并不总是在这里工作,因为对象可能看起来像一种以上的鸭子!
例如,初始化者可以获取其自己的类的文件,字符串或实例.您可能会有以下代码:
class A(object):
def __init__(self, f):
if isinstance(f, A):
# Just make a copy.
elif isinstance(f, file):
# initialise from the file
else:
# treat f as a string
Run Code Online (Sandbox Code Playgroud)
在这里使用EAFP可能会导致各种细微问题,因为每个初始化路径在抛出异常之前都会部分运行.基本上这种结构模仿函数重载,因此不是非常Pythonic,但如果小心使用它可能是有用的.
作为旁注,你不能在Python 3中以相同的方式进行文件检查.你需要这样的东西isinstance(f, io.IOBase)
.
drx*_*zcl 26
这里的主导范式是EAFP:比获得更容易请求宽恕.继续使用文件接口,然后处理生成的异常,或让它们传播给调用者.
Ben*_*ott 11
通过检查条件来引发错误通常很有用,因为通常直到很久之后才会引发该错误.对于"user-land"和"api"代码之间的边界尤其如此.
你不会在出口门的警察局放置金属探测器,你会把它放在入口处!如果不检查条件意味着可能发生错误,可能已经被捕获了100行,或者在超类中而不是在子类中被引发,那么我说检查没有任何问题.
当您接受多种类型时,检查正确的类型也是有意义的.最好提出一个异常,说"我需要一个basetring,OR文件的子类",而不仅仅是因为某个变量没有'seek'方法而引发异常...
这并不意味着你疯了,到处都这样做,因为大多数情况下我同意异常提升自己的概念,但是如果你可以使你的API大大清楚,或者避免不必要的代码执行因为一个简单的条件没有得到满足这样做!
您可以尝试调用该方法然后捕获异常:
try:
fp.read()
except AttributeError:
raise something
Run Code Online (Sandbox Code Playgroud)
如果您只想要读取和写入方法,则可以执行以下操作:
if not (hasattr(fp, 'read') and hasattr(fp, 'write')):
raise something
Run Code Online (Sandbox Code Playgroud)
如果我是你,我会选择try/except方法.
归档时间: |
|
查看次数: |
42869 次 |
最近记录: |