Nli*_*tis 11 python exception introspection object
我知道这可能听起来像一个愚蠢的问题,特别是对于那些了解python本质的人,但我只是想知道,有没有办法知道一个对象是否"实现了一个接口"以便说出来?
举一个我想说的例子:
假设我有这个功能:
def get_counts(sequence):
counts = {}
for x in sequence:
if x in counts:
counts[x] += 1
else:
counts[x] = 1
return counts
Run Code Online (Sandbox Code Playgroud)
我的问题是:有没有办法确保传递给函数的对象是iterable?我知道在Java或C#中我可以通过让方法接受任何实现特定接口的对象来实现这一点,让我们说(例如)iIterable像这样:void get_counts(iIterable sequence)
我的猜测是,在Python中,我必须采用抢占式内省检查(在一个decorator 或许?中)并exception在对象没有__iter__属性的情况下抛出自定义.但有更多的pythonic方式来做到这一点?
eca*_*mur 10
Python(自2.6起)具有抽象基类(也称为虚拟接口),它比Java或C#接口更灵活.要检查对象是否可迭代,请使用collections.Iterable:
if isinstance(obj, collections.Iterable):
...
Run Code Online (Sandbox Code Playgroud)
但是,如果您的else块只会引发异常,那么大多数Python的答案是:不要检查!您的来电者可以通过合适的类型传递; 你只需要记录你期望一个可迭代的对象.
isinstance()或interfaces 之前使用多态和duck-typing你通常定义要怎样做你的对象,那么无论使用多态来调整每个对象如何回应你想要做什么,或者你用鸭打字; 测试手头的物体是否可以做你想做的事情.这是调用与内省权衡的关系,传统观点认为调用优于内省,但在Python中,鸭子类型优于isinstance测试.
所以你需要弄清楚为什么你需要过滤或不首先可迭代的东西; 为什么你需要知道这个?只需使用a try: iter(object),except TypeError: # not iterable进行测试.
或者,如果传递的任何内容都不是可迭代的,那么您可能只需要抛出异常,因为这会发出错误信号.
使用duck-typing,您可能会发现必须测试多种方法,因此isinstance()测试可能看起来更好.在这种情况下,使用抽象基类(ABC)也可以是一种选择; 例如,使用ABC让你"绘制"几个不同的类作为给定操作的正确类型.使用ABC让您专注于需要执行的任务而不是使用的特定实现; 你可以有PaintableABC,PrintableABC等
如果你发现你的应用程序正在使用的可怕的很多基本知识,或者你一直有一个多态方法添加到您的类来应对各种不同的情况,下一步就是如考虑使用全面的组件体系结构,Zope的组件架构(ZCA).
zope.interface接口是类固醇的ABCs,特别是当与ZCA适配器结合使用时.接口记录了类的预期行为:
if IFrobnarIterable.providedBy(yourobject):
# it'll support iteration and yield Frobnars.
Run Code Online (Sandbox Code Playgroud)
但它也让你看起来适配器; 您可以实现适配器以针对特定用例提供多态行为,而不是将所有行为用于表中的每个形状使用.您可以将对象调整为可打印,可迭代或可导出为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)
Run Code Online (Sandbox Code Playgroud)
并且您的代码只需查找每个形状的适配器:
for obj in setofobjects:
self.result.append(IXMLExport(obj).export())
Run Code Online (Sandbox Code Playgroud)