在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
也许是?)并抛出一个自定义)。但是,有没有更 Python的 方式来做到这一点?exception``__iter__
__
问题答案:
在isinstance()
or接口之前使用多态和鸭式输入
你通常定义要怎样 做 你的对象,那么无论使用多态,怎么每个对象响应调整到你想要做什么,或者你用鸭打字;
首先测试对象是否可以做您想做的事情。这是调用与内省之间的权衡,传统观点认为,调用比自省要好,但是在Python中,鸭子类型胜于isinstance
测试。
因此,您需要弄清楚 为什么 首先需要过滤或不过滤某些东西。你为什么需要知道这个?只需使用一个try: iter(object)
,except TypeError: # not iterable
来测试。
或者,如果传递的内容不是可迭代的,则可能只需要引发异常,因为这将表明错误。
美国广播公司
使用鸭式输入法,您可能会发现必须测试多种方法,因此isinstance()
测试可能是更好的选择。在这种情况下,也可以选择使用抽象基类(ABC)。例如,使用ABC,您可以将几种不同的类“绘制”为给定操作的正确类型。使用ABC,您可以专注于需要执行的任务,而不是所使用的特定实现。您可以拥有Paintable
ABC,Printable
ABC等。
Zope接口和组件架构
如果你发现你的应用程序正在使用的 可怕的
很多基本知识,或者你一直有一个多态的方法来你的类添加应对各种不同的情况,下一步就是如考虑使用全面的组件体系结构,Zope的组件架构(ZCA)。
zope.interface
接口是类固醇上的ABC,尤其是与ZCA适配器结合使用时。接口记录了类的预期行为:
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())