Невозможно создать абстрактный класс... с абстрактными методами

Я работаю над своего рода lib, и по какой-то странной причине у меня есть эта ошибка.

  • Вот мой код. Конечно, abc.abstractmethod необходимо расколоть
  • Вот мои тесты

Извините, не удалось просто скопировать и вставить его

Я исходил из того, что приведенный ниже код

test.py

import abc
import six

@six.add_metaclass(abc.ABCMeta)
class Base(object):

    @abc.abstractmethod
    def whatever(self,):
        raise NotImplementedError

class SubClass(Base):

    def __init__(self,):

        super(Base, self).__init__()
        self.whatever()

    def whatever(self,):
        print("whatever")

В оболочке python

>>> from test import *
>>> s = SubClass()
whatever

Почему для моего модуля реестра у меня такая ошибка

Can't instantiate abstract class Player with abstract methods _Base__json_builder, _Base__xml_builder

заранее спасибо

Ответы

Ответ 1

Ваша проблема возникает из-за того, что вы определили абстрактные методы в базовом абстрактном классе с добавлением __ (double underscore). Это приводит к тому, что python выполняет манипуляцию имени во время определения классов.

Имена функции изменяются с __json_builder на _Base__json_builder или __xml_builder на _Base__xml_builder. И это имя, которое вы должны реализовать/перезаписать в своем подклассе.

Чтобы показать это поведение в вашем примере -

>>> import abc
>>> import six
>>> @six.add_metaclass(abc.ABCMeta)
... class Base(object):
...     @abc.abstractmethod
...     def __whatever(self):
...             raise NotImplementedError
...
>>> class SubClass(Base):
...     def __init__(self):
...             super(Base, self).__init__()
...             self.__whatever()
...     def __whatever(self):
...             print("whatever")
...
>>> a = SubClass()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class SubClass with abstract methods _Base__whatever

Когда я меняю реализацию на следующую, она работает

>>> class SubClass(Base):
...     def __init__(self):
...             super(Base, self).__init__()
...             self._Base__whatever()
...     def _Base__whatever(self):
...             print("whatever")
...
>>> a = SubClass()
whatever

Но это очень утомительно, вы можете подумать, хотите ли вы определить свои функции с помощью __ (double underscore). Вы можете прочитать больше о названии коверкая здесь.

Ответ 2

Эта ошибка появляется из исходного кода python. Вот почему мы не видим линии реального исключения.

PyErr_Format(PyExc_TypeError,        
             "Can't instantiate abstract class %s "
             "with abstract methods %U",
             type->tp_name,
             joined);

Я клонировал исходный код python из github. Это из файла typeobject.c.