Я не вижу то, что я ожидаю, когда я буду использовать ABCMeta и abstractmethod.
Это хорошо работает в python3:
from abc import ABCMeta, abstractmethod
class Super(metaclass=ABCMeta):
@abstractmethod
def method(self):
pass
a = Super()
TypeError: Can't instantiate abstract class Super ...
И в 2,6:
class Super():
__metaclass__ = ABCMeta
@abstractmethod
def method(self):
pass
a = Super()
TypeError: Can't instantiate abstract class Super ...
Они оба также хорошо работают (я получаю ожидаемое исключение), если я происхожу Супер из объекта, в дополнение к ABCMeta.
Они оба "перестали работать" (никакое повышенное исключение), если я происхожу Супер из списка.
Я хочу, чтобы абстрактный базовый класс был списком, но кратким обзором и бетоном в sub классах.
Я делаю его неправильно, или разве я не должен хотеть это в Python?
В сборке Super
, как в ваших рабочих фрагментах, вы вызываете, когда выполняете Super ()
:
>>> Super.__init__
<slot wrapper '__init__' of 'object' objects>
Если Super
наследуется от list
, назовите его Superlist
:
>>> Superlist.__init__
<slot wrapper '__init__' of 'list' objects>
Теперь абстрактные базовые классы предназначены для использования как классы mixin , чтобы быть умножить унаследованный от (чтобы получить возможности шаблона проектирования «Метод шаблона», которые может предложить ABC) вместе с конкретным классом, не делая результирующий потомок абстрактным. Итак, подумайте:
>>> class Listsuper(Super, list): pass
...
>>> Listsuper.__init__
<slot wrapper '__init__' of 'list' objects>
Видите проблему? По правилам множественного наследования, вызов Listsuper ()
(который не может завершиться ошибкой только потому, что есть висящий абстрактный метод) запускает тот же код, что и вызов Superlist ()
(который вы бы хотели провалить). На практике этот код ( list .__ init __
) не не возражает против висящих абстрактных методов - только объект .__ init __
. И исправление этого, вероятно, сломало бы код, который зависит от текущего поведения.
Предлагаемый обходной путь: если вам нужен абстрактный базовый класс, все его основы должны быть абстрактными.Итак, вместо того, чтобы иметь конкретный список
среди ваших баз, используйте в качестве базы collections.MutableSequence
, добавьте __ init __
, который составляет ._ list
] и реализовать абстрактные методы MutableSequence
путем прямого делегирования в self._list
. Не идеально, но и не так уж больно.