まず、abc
モジュールを間違って使用しています(see the docs)。あなたのクラスA
はabc.ABCMeta
をメタクラスとして持つべきです。したがって、既にメタクラスを使用している場合は、それをあなたの利点にまで拡張することができます。
abstractmethod
仕事をするためにabc.ABCMeta
から継承し、do_thing
を飾るメタクラス:
from abc import ABCMeta, abstractmethod
class DecoratingMeta(ABCMeta):
def __new__(cls, *args):
new_class = super(DecoratingMeta, cls).__new__(cls, *args)
# decorating do_thing manually
new_class.do_thing = new_class.do_thing_decorator(new_class.do_thing)
return new_class
何もしない、デフォルトのチェックデコレータで今すぐあなたの抽象ベースクラス:
# class Abstract(metaclass=ABCMeta): in python3
class Abstract(object):
__metaclass__ = DecoratingMeta # remove this line in python3
@abstractmethod
def do_thing(self, input):
pass
@classmethod
def do_thing_decorator(cls, function):
return function # default decorator that does nothing
注do_thing_decorator
ことこの場合、クラスメソッドでなければなりません。 python3
およびpython2
で動作するメタクラスについては、sixを参照してください。のみ、特定のチェッカーを実装していますが、まだ抽象的である
あなたのチェッカークラス:あなたはcheck = do_thing_func(input)
を書いた行は再帰エラーになるだろうと
class Checker(Abstract):
@classmethod
def do_thing_decorator(cls, function):
def do_checked_thing(self, input):
check = function(self, input) # NOT self.do_thing(input) else recursion error
if check != 1:
raise ValueError("Check failed")
return check
return do_checked_thing
注意。
そしてdo_thing
のサンプル実装を使用して、具体的なクラス:
class Concrete(Checker):
def do_thing(self, input):
return input # sample implementation
あなたはdo_thing(1)
が成功したことを確認することができますし、do_thing(2)
は、このアプローチの欠点は、あなたが作ることができないということです
c = Concrete()
c.do_thing(1)
try:
c.do_thing(2)
except ValueError:
print("check failed")
を失敗しました要約書。
だから、これはすでに大量のテキストだったが、あなたはまったくのメタクラスを使用しない場合は、はるかに簡単な方法があります:
はでdo_thing
方法でチェックを実行するクラスを書きますdo_thing_func
とcheck_do_thing
が本当に抽象的、あなたがタイプAbstract
のまだインスタンス化するオブジェクトをできることではないことを
class Abstract(object):
def do_thing_func(self, input):
raise NotImplementedError()
def check_do_thing(self, result):
raise NotImplementedError()
# don't override this method
def do_thing(self, input):
result = self.do_thing_func(input)
self.check_do_thing(result) # may raise
return result # if it does not raise return the result
注:2「抽象」メソッドを使用して。それらを抽象的にする必要がある場合は、標準abc.ABCMeta
メタクラスをここで使用してください。
は、今、私たちはここにデコレータを必要としないので、これは非常に簡単になりcheck_do_thing
class Checker(Abstract):
def check_do_thing(self, result):
if result != 1:
raise ValueError("check failed")
実装チェッカークラスを作成します。
そしてConcrete
は今do_thing_func
を実装する必要がありますが、あなたはクラスを使用するときにdo_thing
を呼び出す必要があることdo_thing_func
class Concrete(Checker):
def do_thing_func(self, input):
return input # sample implementation
注意を実装して、最後に具体的なクラス。
ここでの短所は、do_thing
を上書きしてチェックを破棄できることです。
あなたは '__new __()'メソッドを見たことがありますか? –
@ IgnacioVazquez-Abramsは不合理な解決策ではありません。私は、メソッドレベルでもう少し直感的なものを望んでいましたが、何か良いものが見つからなければ、おそらくデフォルトになります。 –