Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查对象是否与Python中的文件类似_Python_File - Fatal编程技术网

检查对象是否与Python中的文件类似

检查对象是否与Python中的文件类似,python,file,Python,File,Python中的对象的行为类似于真实文件,例如具有read()和write method(),但其实现与文件不同。这是概念的实现 在需要文件的任何地方都允许使用类似文件的对象,这被认为是一种很好的做法,因此,例如,可以使用套接字对象代替真实文件。因此,执行这样的检查是不好的: if not isinstance(fp, file): raise something 检查对象(例如方法的参数)是否“类似文件”的最佳方法是什么?您可以尝试调用该方法,然后捕获异常: try: fp.r

Python中的对象的行为类似于真实文件,例如具有read()和write method(),但其实现与
文件
不同。这是概念的实现

在需要文件的任何地方都允许使用类似文件的对象,这被认为是一种很好的做法,因此,例如,可以使用套接字对象代替真实文件。因此,执行这样的检查是不好的:

if not isinstance(fp, file):
   raise something

检查对象(例如方法的参数)是否“类似文件”的最佳方法是什么?

您可以尝试调用该方法,然后捕获异常:

try:
    fp.read()
except AttributeError:
    raise something
如果您只需要读写方法,可以执行以下操作:

if not (hasattr(fp, 'read') and hasattr(fp, 'write')):
   raise something

如果我是你,我会使用try/except方法。

这里的主要范例是EAFP:请求原谅比允许更容易。继续使用文件接口,然后处理产生的异常,或者让它们传播给调用者。

除非有特殊要求,否则在代码中进行这样的检查通常不是一个好做法

在Python中,键入是动态的,为什么您觉得需要检查对象是否类似文件,而不是像文件一样使用它并处理结果错误


无论如何,您可以执行的任何检查都将在运行时进行,因此执行类似于
if not hasattr(fp,'read')
的操作并引发一些异常只会比调用
fp.read()提供更多的实用性
并在方法不存在时处理结果属性错误。

正如其他人所说,通常应避免此类检查。一个例外是,对象可能合法地是不同的类型,并且您希望根据不同的类型有不同的行为。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
在这里使用EAFP可能会导致各种微妙的问题,因为每个初始化路径在引发异常之前都会部分运行。 从本质上说,这种结构模拟函数重载,因此不是很符合Python,但如果小心使用,它会很有用


作为补充说明,在Python3中不能以同样的方式进行文件检查。您将需要类似isinstance(f,io.IOBase)的东西。在大多数情况下,处理此问题的最佳方法是不使用。如果一个方法接受一个类似于文件的对象,而它所传递的对象却不是,那么当该方法尝试使用该对象时引发的异常的信息量不会比您可能显式引发的任何异常少

不过,至少有一种情况下,您可能希望执行此类检查,即当您将对象传递给的对象没有立即使用该对象时,例如,如果在类的构造函数中设置该对象。在这种情况下,我认为EAFP的原则被“fail fast”的原则所压倒。我会检查对象以确保它实现了我的类需要的方法(并且它们是方法),例如:


通过检查条件来引发错误通常是有用的,因为通常情况下,直到很久以后才会引发错误。这对于“用户土地”和“api”代码之间的边界尤其如此

你不会把金属探测器放在警察局的出口门上,你会把它放在入口处!如果不检查一个条件意味着可能会发生一个错误,这个错误可能在100行之前被捕获,或者在一个超类中而不是在子类中被引发,那么我说检查没有错

当您接受多个类型时,检查正确的类型也是有意义的。 最好引发一个异常,说明“我需要一个basestring或file的子类”,而不是仅仅引发一个异常,因为某些变量没有“seek”方法


这并不意味着你会发疯,到处这样做,在大多数情况下,我同意异常会自己引发的概念,但是如果你能使你的API非常清晰,或者因为没有满足简单的条件而避免不必要的代码执行,那么就这样做吧

对于3.1+,以下选项之一:

isinstance(something, io.TextIOBase)
isinstance(something, io.BufferedIOBase)
isinstance(something, io.RawIOBase)
isinstance(something, io.IOBase)
对于2.x来说,“类似文件的对象”是一个很模糊的东西,无法检查,但是您正在处理的任何函数的文档都有希望告诉您它们实际需要什么;如果没有,请阅读代码


正如其他答案所指出的,首先要问的是你到底在检查什么。通常,EAFP就足够了,而且更加惯用

表示“类文件对象”是“文件对象”的同义词,这最终意味着它是中定义的三个对象之一的实例,它们本身都是
IOBase
的子类。因此,检查的方法完全如上图所示

(然而,检查
IOBase
并不是很有用。您能想象一个需要区分实际文件(如
read(size))的情况吗
从某个名为
read
的单参数函数中读取,该函数不类似文件,也不需要区分文本文件和原始二进制文件?因此,实际上,您几乎总是希望检查,例如,“是文本文件对象”,而不是“是类似文件的对象”。)


对于2.x,虽然
io
模块自2.6+以来就已经存在,但内置文件对象不是
io
类的实例,也不是stdlib中的任何类似文件的对象,也不是您可能遇到的大多数第三方类似文件的对象。“类似文件的对象”的含义没有官方定义;它只是“像一个内置的东西”,不同的功能意味着不同的东西“像”。这些职能应记录其含义;如果他们没有,你必须看一下代码

但是,最常见的含义是“has
read(size)
”、“has
read()
”或“是字符串的一个iterable”,但一些旧库可能希望使用
readline
isinstance(something, io.TextIOBase)
isinstance(something, io.BufferedIOBase)
isinstance(something, io.RawIOBase)
isinstance(something, io.IOBase)
import os 

if os.path.isfile(path):
   'do something'