Абстрактные базовые классы против типизации утки


Python имеет специальныеАзбуки для типов контейнеров . Он говорит, что они " ... используются для проверки того, предоставляет ли класс определенный интерфейс.- (И что они также полезны для некоторых миксинов, но давайте пока это проигнорируем.)

Мне трудно понять, почему некоторые из этих азбук действительно полезны. Возможно, моя проблема просто в том, что примеры в doc слишком академичны, но используя эти примеры:
# Verbatim
size = None
if isinstance(myvar, collections.abc.Sized):
    size = len(myvar)

# Is that so much better than
size = None
if hasattr(myvar, '__len__'):
    size = len(myvar)

Во втором случае вы избегаете импорта, и код кажется больше откровенно для меня. Вы можете сделать вывод, какие коллекции.азбука.Размер означает от его имени, или искать его, но это просто не так явно, как "если у него есть длина, получить его длину."

Является ли подход abc к тестированию типа коллекции действительно более идиоматичным Python, чем явное тестирование hasattr, и если да, то почему? (Действительно ли простое лучше, чем сложное козырь явное лучше, чем неявное в этом случае?)
2 4

2 ответа:

Мне кажется, что миксины являются основной частью этого модуля. Кроме того, в большинстве случаев, да просто является главной целью, чтобы сделать идеальный код, по крайней мере для меня(не то, чтобы я когда-либо управлял им). Тот факт, что функции модуля ABC, кажется, довольно ясно понимают, что они делают, помогает для совместного использования и скимминга кода. Наконец, я могу ошибаться в этом, поэтому не рассчитывайте на это, хотя я думаю, что некоторые функции ABC могут проверять наличие нескольких атрибутов в одной функции.

Вы можете достичь тех же результатов при любом подходе. Основное преимущество подхода ABC заключается в том, что часть логики предоставляется вам. Например, чтобы реализовать тип набора с помощью duck typing, вам придется написать и протестировать 14 интерфейсов - __contains__, __iter__, __len__, __le__, __lt__, __eq__, __ne__, __gt__, __ge__, __and__, __or__, __sub__, __xor__, and isdisjoint.

Однако, если вы используете ABC, вам нужно только определить __contains__, __iter__ and __len__ - ABC использует эти функции, которые вы предоставляете для реализации оставшихся 11 методов для вас. ABC делает то же, что и вы, но с меньшими усилиями. Это короткий путь, который приведет вас в тот же пункт назначения.