Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.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 如何使类似文件的类与";iInstance(cls,io.IOBase)“;?_Python_File_Class_Isinstance - Fatal编程技术网

Python 如何使类似文件的类与";iInstance(cls,io.IOBase)“;?

Python 如何使类似文件的类与";iInstance(cls,io.IOBase)“;?,python,file,class,isinstance,Python,File,Class,Isinstance,似乎检查isinstance(…,io.IOBase)是确定对象是否为“类似文件”的“正确”方法 但是,在定义我自己的类文件时,它似乎不起作用: 导入io 类文件\u like(): 定义初始化(自): 通过 def写入(自身,行): 打印(“书写:”,行) def关闭(自我): 通过 def冲洗(自): 通过 打印(isinstance(类文件(),io.IOBase)) #打印“假” 如何使其工作?isinstance(obj,某些类)只是迭代obj的继承链,寻找某些类。因此,isinst

似乎检查
isinstance(…,io.IOBase)
是确定对象是否为“类似文件”的“正确”方法

但是,在定义我自己的类文件时,它似乎不起作用:

导入io
类文件\u like():
定义初始化(自):
通过
def写入(自身,行):
打印(“书写:”,行)
def关闭(自我):
通过
def冲洗(自):
通过
打印(isinstance(类文件(),io.IOBase))
#打印“假”
如何使其工作?

isinstance(obj,某些类)
只是迭代obj的继承链,寻找
某些类。因此,
isinstance(file_like,io.IOBase)
将为false,因为您的
file_like
类在其祖先中没有
io.IOBase
<代码>文件\u like
不指定显式父对象,因此它仅隐式地从
对象继承。除了
file\u like
本身之外,这是唯一一个使用
isinstance()对
file\u like
实例测试为阳性的类

您在
file\u like
中所做的是定义类文件对象上所需的方法,而不是从任何特定的“类文件”类继承。这种方法被称为,它在动态语言中有许多优点,尽管它在其他语言(例如Ruby)中比Python更受欢迎。尽管如此,如果您提供的
类文件
实例遵循duck类型,只要您的
类文件
确实“像文件一样嘎嘎”,即其行为足够像文件,在接收端使用时不会导致错误,那么它应该可以工作

当然,如果接收端没有遵循duck类型,例如,像您在这里所做的那样尝试通过
isinstance()
检查类型,那么这种方法将失败

最后,一个小的风格错误:如果类没有显式继承任何内容,则不要将空paren放在类上。它们是多余的。

检查
isinstance(something,io.IOBase)
只检查
something
是否是
io.IOBase
的实例或派生自它的类-所以我不明白你从哪里误解了这是确定对象是否“类似文件”的“正确”方法

另一种方法是使用抽象基类。Python有很多,但目前还没有一个可以与
isinstance()
一起使用的“类文件”。但是,您可以使用中概述的
abc
模块定义自己的代码

webiste有一个使用
abc
模块完成类似操作的方法。这个被高度评价的问题显示了一种定义你自己ABC的类似方式

为了说明如何将其应用到您的案例中,您可以定义这样的ABC及其所有抽象方法,从而强制派生类定义所有这些方法以便实例化:

from abc import ABCMeta, abstractmethod

class ABCFileLike(metaclass=ABCMeta):
    @abstractmethod
    def __init__(self): pass

    @abstractmethod
    def write(self, line): pass

    @abstractmethod
    def close(self): pass

    @abstractmethod
    def flush(self): pass
然后,您可以从中派生自己的具体类,确保提供所有抽象方法的实现。(如果您没有全部定义它们,那么如果尝试实例化它,将引发
TypeError
。)

您甚至可以通过使用新元类注册现有类来向其添加这些类:

import io

print(isinstance(io.IOBase(), ABCFileLike))  # -> False

ABCFileLike.register(io.IOBase)
print(isinstance(io.IOBase(), ABCFileLike))  # -> True

谢谢你的回答。它澄清了我的许多问题。也谢谢你的风格说明,我相信这是从需要paren的函数遗留下来的。我会记下来的
import io

print(isinstance(io.IOBase(), ABCFileLike))  # -> False

ABCFileLike.register(io.IOBase)
print(isinstance(io.IOBase(), ABCFileLike))  # -> True