isinstance()
在或接口之前使用多态性和鸭子类型
您通常定义要对对象执行的操作,然后使用多态性来调整每个对象对您想要执行的操作的响应方式,或者使用鸭子类型;首先测试手头的对象是否可以做你想做的事情。这是调用与自省的权衡,传统观点认为调用优于自省,但在 Python 中,鸭式打字优于isinstance
测试。
因此,您首先需要弄清楚为什么需要过滤某些东西是否是可迭代的;为什么你需要知道这个?只需使用try: iter(object)
,except TypeError: # not iterable
进行测试。
或者,如果传递的任何内容都不是可迭代的,您可能只需要抛出异常,因为这会发出错误信号。
基础知识
使用鸭式打字,您可能会发现您必须测试多种方法,因此isinstance()
测试可能看起来是更好的选择。在这种情况下,也可以选择使用抽象基类 (ABC) ;例如,使用 ABC 让您“绘制”几个不同的类作为给定操作的正确类型。使用 ABC 让您专注于需要执行的任务,而不是使用的具体实现;你可以有一个Paintable
ABC,一个Printable
ABC等。
Zope 接口和组件架构
如果你发现你的应用程序使用了非常多的 ABC,或者你不得不在类中添加多态方法来处理各种不同的情况,那么下一步就是考虑使用成熟的组件架构,例如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())