python - 在 python 中,有没有办法在将对象传递给函数之前知道它是否为 "implements an interface"?

标签 python exception object introspection

我知道这听起来像是一个愚蠢的问题,尤其是对于了解 python 本质的人来说,但我只是想知道,有没有办法知道一个对象是否“实现了一个接口(interface)”以便说?

举个例子说明我想说的:

假设我有这个功能:

def get_counts(sequence):
     counts = {}
     for x in sequence:
         if x in counts:
             counts[x] += 1
         else:
             counts[x] = 1
     return counts

我的问题是:有没有办法确保传递给函数的对象是可迭代我知道在 Java 或 C# 中我可以通过让方法接受实现特定接口(interface)的任何对象,让我们说(例如)iIterable 像这样:void get_counts(iIterable sequence)

我的猜测是,在 Python 中,我必须采用先发制人的自省(introspection)检查(也许在 decorator 中?)并抛出自定义的 exception如果对象没有 __iter__ 属性)。但是有没有更pythonic的方法来做到这一点?

最佳答案

isinstance() 或接口(interface)之前使用多态和鸭子类型

您通常定义要对对象做什么,然后使用多态性来调整每个对象如何响应您想要做的事情,或者使用鸭子类型;首先测试手头的对象是否可以做您想做的事情。这是调用与内省(introspection)的权衡,传统观点认为调用优于内省(introspection),但在 Python 中,duck-typing 优于 isinstance 测试。

所以你首先需要弄清楚为什么你需要过滤某些东西是否是可迭代的;你为什么需要知道这个?只需使用一个try: iter(object), except TypeError: # not iterable 来测试。

或者,如果传递的内容不是可迭代对象,您可能只需要抛出异常,因为这会发出错误信号。

基础知识

使用 duck-typing,您可能会发现必须测试多种方法,因此 isinstance() 测试可能看起来是更好的选择。在这种情况下,使用 Abstract Base Class (ABC)也可以是一种选择;例如,使用 ABC 让您“绘制”几个不同的类作为给定操作的正确类型。使用 ABC 让您专注于需要执行的任务,而不是使用的具体实现;你可以有一个Paintable ABC,一个Printable ABC,等等

Zope 接口(interface)和组件架构

如果您发现您的应用程序使用了很多糟糕的 ABC,或者您一直不得不向您的类中添加多态方法来处理各种不同的情况,那么下一步就是考虑使用一个完整的-组件架构失效,例如 Zope Component Architecture (ZCA) .

zope.interface 接口(interface)是类固醇的基础知识,尤其是与 ZCA 适配器结合使用时。接口(interface)记录类的预期行为:

if IFrobnarIterable.providedBy(yourobject):
    # it'll support iteration and yield Frobnars.

但它也让您查找适配器;您无需将每次使用形状的所有行为都放在类中,而是实现适配器以为特定用例提供多态行为。您可以将您的对象调整为可打印、可迭代或可导出为 XML:

class FrobnarsXMLExport(object):
    adapts(IFrobnarIterable)
    provides(IXMLExport)

    def __init__(self, frobnariterator):
        self.frobnars = frobnariterator

    def export(self):
        entries = []
        for frobnar in self.frobnars:
            entries.append(
                u'<frobnar><width>{0}</width><height>{0}</height></frobnar>'.format(
                    frobnar.width, frobnar.height)
        return u''.join(entries)

并且您的代码只需为每个形状查找适配器:

for obj in setofobjects:
    self.result.append(IXMLExport(obj).export())

关于python - 在 python 中,有没有办法在将对象传递给函数之前知道它是否为 "implements an interface"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13919772/

相关文章:

python - 如何使父类(super class)独有的类属性

python - doctest 中的链式异常

Javascript 对象无法与 native javascript 方法(如 match()、替换等)一起使用

python - 根据两个列表的大小定义多个对象(python)

python - 为什么一个CNN的loss会长时间下降然后突然上升?

python - 如何在 PyCharm for Python 项目中获取代码覆盖率报告

java - 异常发现得太早

c# - 为什么 yield return 不能出现在带有 catch 的 try block 中?

jquery - 将字符串作为对象传递给 jQuery 函数

python - 基于树状模式创建新列