2016-11-10 6 views
4

私はいくつかのメソッドを持ついくつかのメソッドを持っています。このチェックに応じて、メソッドのコードが実行される、またはexecption育てられるだろう。私はデコレータを使っているが、すべてのメソッドの最初に "check"コードを複製するのではなく、デコレータが密接に関連しているので、クラス自体の中にデコレータを埋め込んでほしい。だから、基本的には:?代わりにこの基底クラスと派生クラスの両方の基底クラスのデコレータの使用

class A(object): 

    def a_method(self): 
     if self.check_var is True: 
      (some_code) 
     else: 
      raise Exception 

私はこの

class A(object): 

    def decorator(function): 
     def function_wrapper(self, *args, **kwargs): 
      if self.check_var is True: 
       return function(self, *args, **kwargs) 
      else: 
       raise Exception 
     return function_wrapper 

    @decorator 
    def a_method(self): 
     (some_code) 

私の最初の質問は、私がこの権利についてつもりされて持っていると思いますかまたはより良い方法があります。私はこのチェックを必要とするAクラスの多くのメソッドを持っているので、コードを不必要に複製したくないのです。

2番目の質問は、私がこのように説明した場合、クラスAからクラスを派生させて同じデコレータチェックを実行するときに問題に遭遇します。繰り返しますが、コードを複製したくないので、派生クラスのチェックを行うためにデコレータをベースクラスAに再利用したいと思います。私はデコレータを@classmethodにすることについて読んでいましたが、これを行うとデコレータを派生クラスで使用できますが、基本クラスでは使用できなくなりました。

だから、基本的に私はこのような何か希望:

class A(object): 

    @classmethod #maybe 
    def decorator(function): 
     def function_wrapper(self, *args, **kwargs): 
      if self.check_var is True: 
       return function(self, *args, **kwargs) 
      else: 
       raise Exception 
     return function_wrapper 

    @decorator 
    def a_method(self): 
     (some_code) 

class B(A): 

    @decorator 
    def b_method(self): 
     (some_code) 

はこれを行うための任意のきれいな方法で誰を知っていますか?

+4

'decorator()'を両方のクラスの外側とその前に定義するだけです。 – martineau

+0

私はクラス内にデコレータを持っていたいと思います...デコレータがしていることは、クラスに非常に関連しています – viterbi

+1

デコレータを使ってファイル(モジュール)に基本クラスを置くと、それらが一緒に属していることがかなり明らかです@martineauが言ったこと – user3012759

答えて

3

あなたはクラス内で(というよりも、私はコメントで示唆されているように、それらの両方外)デコレータを置くことを好むので

def get_decorator(function, argument): 
    def function_wrapper(*args, **kwargs): 
     if argument is True: 
      return function(*args, **kwargs) 
     else: 
      raise Exception 
    return function_wrapper 

class A(object): 
    def __init__(self): 
     self.check_var = True 
     self.a_method = get_decorator(self.a_method, self.check_var) 
    def a_method(self): 
     (whatever) 

class B(A): 
    def __init__(self): 
     super(B, self).__init__() 
     self.b_method = get_decorator(self.b_method, self.check_var) 
    def b_method(self): 
     (whatever) 
は、以下のことを実行する方法を示しています。デコレータは classmethodの代わりに staticmethodになりますが、若干珍しいやり方で使用する必要がありますが、 以内にはクラス内のみです。

このようなデコレータを使用する必要性に関する詳細については、ターニング延期することになり、私の質問__func__を使用すると、まだ最初のクラスで定義を維持することを避けるためにCalling class staticmethod within the class body?

class A(object): 
    @staticmethod 
    def decorator(function): 
     def function_wrapper(*args, **kwargs): 
      print('in function_wrapper') 
      return function(*args, **kwargs) 
     return function_wrapper 

    @decorator.__func__ #### Note unusual decorator usage inside defining class 
    def a_method(self): 
     print('in a_method') 

class B(A): 
    @A.decorator #### Normal decorator usage outside defining class 
    def b_method(self): 
     print('in b_method') 

一つの方法を参照してくださいそのクラス定義の非常に最後までstaticmethodへ:__func__はこのようなものです回避するためのさらに別の方法

class A(object): 
    def decorator(function): 
     def function_wrapper(*args, **kwargs): 
      print('in function_wrapper') 
      return function(*args, **kwargs) 
     return function_wrapper 

    @decorator 
    def a_method(self): 
     print('in a_method') 

    decorator = staticmethod(decorator) #### convert for use outside this class 

class B(A): 
    @A.decorator 
    def b_method(self): 
     print('in b_method') 

class A(object): 
    class Check: 
     @staticmethod 
     def decorator(function): 
      def function_wrapper(*args, **kwargs): 
       print('in function_wrapper') 
       return function(*args, **kwargs) 
      return function_wrapper 

    @Check.decorator 
    def a_method(self): 
     print('in a_method') 

class B(A): 
    Check = A.Check 

    @Check.decorator 
    def b_method(self): 
     print('in b_method') 

デコレータの使用を非常に均一にするという追加の利点があります。

+0

ありがとう@martineau!うまくいくようだ – viterbi

0

martineauが以下に述べたように、クラスの外にある古典的なデコレータを置くのがよい方法です。

Classic decorator is called during class creation time, which is long before an instance is created. Reference

+0

私は、OPがデコレータをクラスAとサブクラスBの両方で使用したいという要点を見逃したと思います。それを定義するクラスの中でclassmethodデコレータをコール/使用すると、 'TypeError: 'クラスメソッド'オブジェクトがコール可能ではない'になります。 – martineau

+0

私は知っている、私はちょうど複数の継承について考えるが、それは良い解決策ではないようだ。 –

+0

答えの後半はOPのニーズに対応していません。 – martineau

関連する問題