次のコードでは、ベース抽象クラスBase
を作成します。 Base
から継承するすべてのクラスにname
プロパティを提供するため、このプロパティを@abstractmethod
にしました。
次に、Base_1
と呼ばれるBase
のサブクラスを作成しました。これは、いくつかの機能を提供するためのものですが、抽象のままです。 Base_1
にはname
プロパティはありませんが、それでもpythonエラーなしでそのクラスのオブジェクトをインスタンス化します。どのように抽象プロパティを作成しますか?
from abc import ABCMeta, abstractmethod
class Base(object):
__metaclass__ = ABCMeta
def __init__(self, strDirConfig):
self.strDirConfig = strDirConfig
@abstractmethod
def _doStuff(self, signals):
pass
@property
@abstractmethod
def name(self):
#this property will be supplied by the inheriting classes
#individually
pass
class Base_1(Base):
__metaclass__ = ABCMeta
# this class does not provide the name property, should raise an error
def __init__(self, strDirConfig):
super(Base_1, self).__init__(strDirConfig)
def _doStuff(self, signals):
print 'Base_1 does stuff'
class C(Base_1):
@property
def name(self):
return 'class C'
if __== '__main__':
b1 = Base_1('abc')
Python 3. 以降、バグが修正され、property()
デコレータが抽象メソッドに適用されたときに抽象として正しく識別されるようになりました。
注:順序は重要です。@property
の前に@abstractmethod
を使用する必要があります
Python 3.3 +:( python docs ):
class C(ABC):
@property
@abstractmethod
def my_abstract_property(self):
...
Python 2:( python docs )
class C(ABC):
@abstractproperty
def my_abstract_property(self):
...
Python 3. までは、@abstractmethod
および@property
。
つかいます @abstractproperty
抽象プロパティを作成します( docs )。
from abc import ABCMeta, abstractmethod, abstractproperty
class Base(object):
# ...
@abstractproperty
def name(self):
pass
コードで正しい例外が発生するようになりました。
トレースバック(最後の最後の呼び出し): ファイル「foo.py」、36行目、 b1 = Base_1( 'abc') TypeError:Can '抽象メソッドname で抽象クラスBase_1をインスタンス化しません
上記のジェームズの回答に基づいて
def compatibleabstractproperty(func):
if sys.version_info > (3, 3):
return property(abstractmethod(func))
else:
return abstractproperty(func)
デコレータとして使用します
@compatibleabstractproperty
def env(self):
raise NotImplementedError()