web-dev-qa-db-ja.com

抽象メソッドで抽象クラスをインスタンス化できません...

私は一種のライブラリに取り組んでいますが、奇妙な理由でこのエラーがあります。

  • ここ は私のコードです。もちろん@ 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 Shell

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

私のrosterモジュールがこのエラーになっている理由

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

前もって感謝します

25
josuebrunel

問題は、__(二重アンダースコア)を前に付けて基本抽象クラスで抽象メソッドを定義したために発生します。これにより、クラスの定義時にpythonが name mangling を実行します。

関数の名前が__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

しかし、これは非常に面倒です。本当に__(二重アンダースコア)を使用して関数を定義するかどうかを検討することをお勧めします。名前のマングリングの詳細については、 here を参照してください。

31
Anand S Kumar

このエラーは、Pythonのソースコードから表示されます。それが本当の例外の行が表示されない理由です。

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

python githubのソースコードを複製しました。これはtypeobject.cファイルからのものです。

1
Taras Vaskiv