Ответ 1
Использовать полиморфизм и утиную печать до isinstance()
или интерфейсов
Обычно вы определяете, что хотите делать с вашими объектами, либо используйте полиморфизм, чтобы настроить, как каждый объект реагирует на то, что вы хотите сделать, или вы используете печатание утки; если объект под рукой может сделать то, что вы хотите сделать в первую очередь. Это взаимозависимость по сравнению с компромиссом самоанализа, общепринятая мудрость утверждает, что вызов предпочтительнее интроспекции, но в Python предпочтение отдается методу тестирования isinstance
.
Итак, вам нужно разобраться, почему вам нужно фильтровать на нем, или что-то в этом нетребоваемо; Зачем тебе это нужно знать? Просто используйте теги try: iter(object)
, except TypeError: # not iterable
для тестирования.
Или, возможно, вам просто нужно выдать исключение, если все, что было передано, не было итерабельным, поскольку это могло бы сигнализировать об ошибке.
ABCs
С утиным типом, вы можете обнаружить, что вам нужно проверить несколько методов, и, следовательно, тест isinstance()
может выглядеть лучше. В таких случаях использование опции Абстрактный базовый класс (ABC) также может быть вариантом; Например, использование ABC позволяет вам "рисовать" несколько разных классов как подходящий тип для данной операции. Использование ABC позволяет сосредоточиться на задачах, которые необходимо выполнить, а не на конкретных используемых реализациях; вы можете иметь Paintable
ABC, a Printable
ABC и т.д.
Интерфейсы Zope и архитектура компонентов
Если вы обнаружите, что ваше приложение использует огромное количество ABC или вам нужно добавлять полиморфные методы в свои классы для решения различных ситуаций, следующий шаг - рассмотреть возможность использования полномасштабной архитектуры компонентов, например, Zope Component Architecture (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())