【问题标题】:Python 3: Determine if object supports IOPython 3:确定对象是否支持 IO
【发布时间】:2011-08-17 00:12:38
【问题描述】:

一些 Python 方法适用于各种输入源。例如,XML 元素树parse 方法接受一个对象,该对象可以是字符串(在这种情况下,API 将其视为文件名),也可以是支持 IO 接口的对象,如文件对象或 @987654322 @。

所以,显然parse 方法正在执行某种接口嗅探,以找出要采取的行动方案。我想实现这一点的最简单方法是通过说isinstance(x, str) 检查输入参数是否为字符串,如果是则将其视为文件名,否则将其视为 IO 对象。

但为了更好的错误检查,我认为最好检查 x 是否支持 IO 接口。检查对象是否支持指定接口的标准惯用方法是什么?

我想,一种方法就是说:

if "read" in x.__class__.__dict__: # check if object has a read method

但仅仅因为x 有一个“读取”方法并不一定意味着它支持 IO 接口,所以我假设我还应该检查 IO 接口中的每个方法。这通常是最好的方法吗?还是我应该忘记检查接口,而让可能的AttributeError 在堆栈中进一步处理?

【问题讨论】:

    标签: python interface python-3.x


    【解决方案1】:

    或者我应该忘记检查接口,而只是让可能的AttributeError 在堆栈中进一步处理?

    一般的 pythonic 原则似乎是对你得到的对象做任何你想做的事情,并捕获它可能导致的任何异常。这就是所谓的duck typing。但是,这并不一定意味着您应该让这些异常从您的函数滑到调用代码中。如果能够以有意义的方式处理它们,您可以在函数本身中处理它们。

    【讨论】:

      【解决方案2】:

      Python 强烈鼓励使用鸭子类型:假设传入的对象是有效的并尝试使用它。这样,您的代码就尽可能灵活。当然,如果您的代码的操作取决于传入的对象的类型,那么您确实需要某种类型的检查。我建议尽量减少这种类型检查,并选择isinstance(x, str)

      如果你传入的对象既不是字符串也不支持 IO 接口,这将导致AttributeError。如果发生这种情况,这是调用代码中的错误。这个异常不应该在任何地方处理——而是应该修复错误!

      也就是说,您可以使用

      isinstance(x, io.IOBase)
      

      测试支持 I/O 协议的内置类。不过,这会将您的代码限制为实际派生自 io.IOBase 的类——这是一种肤浅且不必要的限制。

      【讨论】:

      • 我要补充一点,检查接口并不会阻止符合要求的类不做它应该做的事情,这使得检查变得多余。
      • io.IOBase 是一个抽象基类,因此您不需要继承它来使 isinstance/issubclass 工作
      • @gnibbler:你要么需要从它派生,要么需要使用IOBase.register()注册你自己的类型。我仍然认为这是一个不必要的并发症,并没有带来太多好处。
      【解决方案3】:

      是的,python 都是关于鸭子类型的,检查一些方法来确定对象是否支持 IO 接口是完全可以接受的。有时,尝试在 try/except 块中调用您的方法并捕获 TypeErrorValueError 甚至是有意义的,这样您就知道它是否真的支持相同的接口(但要谨慎使用)。我会说使用hasattr 而不是查看__class__.__dict__,否则我会采用这种方法。

      (一般来说,我会先检查标准库中是否还没有方法来处理这样的事情,因为自己决定什么构成“IO 接口”很容易出错。对于例如,typesinspect 模块中有一些方便的 gem 用于相关的接口检查。)

      【讨论】:

      • 哦,如果您决定将任何不是字符串的对象视为 IO 对象,请确保使用isinstance(x, types.StringTypes),而不是isinstance(x, str),因为isinstance(u'foo', str) 返回False。跨度>
      • 但仔细想想,最后一个警告不适用于 Python 3,所以...继续。
      • 在 Python 2.x 中,您通常使用isinstance(x, basestring) 来检查unicodestr
      猜你喜欢
      • 2014-08-16
      • 2013-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-07
      • 2014-08-05
      • 2012-11-13
      相关资源
      最近更新 更多