在python中,有没有一种方法可以在我将对象传递给函数之前知道它是否“实现了一个接口”?

2024-10-04 11:36:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道这听起来可能是一个愚蠢的问题,尤其是对于了解python本质的人来说,但是我想知道,有没有一种方法可以知道一个对象是否“实现了一个接口”?

举个我想说的例子:

假设我有这个函数:

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

我的问题是:有没有办法确保传递给函数的对象是iterable我知道在Java或C中,我可以通过让方法接受实现特定接口的任何对象来实现这一点,比如说(例如)iIterable,如下所示:void get_counts(iIterable sequence)

我的猜测是,在Python中,我必须使用先发制人的内省检查(可能是在decorator中?)如果对象没有__iter__属性,则抛出一个自定义exception)。但有没有比Python更能做到这一点的方法呢?在


Tags: 对象方法函数inforgetreturnif
3条回答

Python(从2.6开始)有abstract base classes(又名虚拟接口),比Java或C接口more flexible。要检查对象是否可编辑,请使用^{}

if isinstance(obj, collections.Iterable):
    ...

但是,如果您的else块只会引发一个异常,那么大多数Python的答案是:不要检查!这取决于调用方传递适当的类型;您只需要记录期望的iterable对象。在

isinstance()或接口

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

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

或者,如果传递的内容不是iterable,那么您可能只需要抛出一个异常,因为这将意味着一个错误。在

ABCs

使用duck类型,您可能会发现您必须测试多个方法,因此isinstance()测试可能是一个更好的选择。在这种情况下,使用Abstract Base Class (ABC)也可以是一种选择;例如,使用ABC让您将几个不同的类“绘制”为给定操作的正确类型。使用ABC让您将注意力集中在需要执行的任务上,而不是使用特定的实现;您可以使用PaintableABC、PrintableABC等

Zope接口和组件架构

如果您发现您的应用程序使用了大量的abc,或者您不得不向类中添加多态方法来处理各种不同的情况,那么下一步就是考虑使用一个完整的组件体系结构,比如Zope Component Architecture (ZCA)。在

zope.interface接口是甾体上的abc,尤其是与ZCA适配器结合时。接口记录类的预期行为:

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

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

^{pr2}$

代码只需为每个形状查找适配器:

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

Python式的方法是使用鸭子打字和“请求原谅,而不是许可”。这通常意味着在try块中执行一个操作,假设它的行为符合预期,然后在except块中处理其他情况。在

相关问题 更多 >