2012-05-09 15 views
2

Pythonで簡略化されたTerm Rewriting System(TRS)/ Symbolic Algebra Systemを実装する方法を試しています。 これは、クラスインスタンスのインスタンス化プロセス中に特定のケースでオペランドをインターセプトして変更できるようにすることが本当に好きです。 私が思いついた解決策は、典型的な( 'タイプ'タイプの)クラスオブジェクトの動作を変更するメタクラスを作成することでした。今、この、だから> F(A、B、C)Python:クラスインスタンスの初期化の前に渡された引数を変更する

class Flat(object): 
    """ 
    Use for associative Operations to expand nested 
    expressions of same Head: F(F(x,y),z) => F(x,y,z) 
    """ 
    __metaclass__ = Preprocess 
    @classmethod 
    def _preprocess_(cls, *operands, **kwargs): 
     head = [] 
     for o in operands: 
      if isinstance(o, cls): 
       head += list(o.operands) 
      else: 
       head.append(o) 
     return tuple(head), kwargs 

-

class Preprocess(type): 
    """ 
    Operation argument preprocessing Metaclass. 
    Classes using this Metaclass must implement the 
     _preprocess_(*operands, **kwargs) 
    classmethod. 
    """ 

    def __call__(cls, *operands, **kwargs): 
     pops, pargs = cls._preprocess_(*operands, **kwargs) 
     return super(Preprocess, cls).__call__(*pops, **pargs) 

例の場合は、ネストされた操作F(F(a、b)は、c)を展開することであろう動作は継承によって実現することができます。

class Operation(object): 
    def __init__(self, *operands): 
     self.operands = operands 

class F(Flat, Operation): 
    pass 

これは、所望の動作につながる:

print F(F(1,2,3),4,5).operands 
(1,2,3,4,5) 

しかし、私はそのような前処理クラスをいくつか組み合わせて、自然クラスのmroに従ってオペランドを順次処理したいと思います。

class Orderless(object): 
    """ 
    Use for commutative Operations to bring into ordered, equivalent 
    form: F(*operands) => F(*sorted(operands)) 
    """ 
    __metaclass__ = Preprocess 

    @classmethod 
    def _preprocess_(cls, *operands, **kwargs): 

     return sorted(operands), kwargs 

これは望みどおりに機能していないようです。フラット・オーダーレス・オペレーション・タイプの定義

結果は、最初の前処理スーパークラスのみが「アクティブ」になります。

print G(G(3,2,1),-1,-3).operands 
(3,2,1,-1,-3) 

どのように私はすべての前処理クラス前処理メソッドは、クラスのインスタンス化の前に呼び出されていることを確認することができますか?

更新:

私は正式に起因する新しいstackoverflowのユーザーとしての私の状態にはまだ私の質問に答えるように見えることはできません。 だから、私はこれはおそらく、私が思い付くことができる最高のソリューションであると考えている:

class Preprocess(type): 
    """ 
    Abstract operation argument preprocessing class. 
    Subclasses must implement the 
     _preprocess_(*operands, **kwargs) 
    classmethod. 
    """ 

    def __call__(cls, *operands, **kwargs): 
     for cc in cls.__mro__: 
      if hasattr(cc, "_preprocess_"): 
       operands, kwargs = cc._preprocess_(*operands, **kwargs) 

     return super(Preprocess, cls).__call__(*operands, **kwargs) 

私は問題は予想通りsuper(Preprocess, cls).__call__(*operands, **kwargs)は、CLSのMROを横断していないということですね。

+0

アロケータをオーバーライドして、ベースを調べるようにします。 –

+0

うーん、どうしたらうまくいくの?プリプロセス.__ call__メソッドでclsオブジェクトの__bases__を印刷すると、(期待どおり) ( __main __、 __main __。Operation '>) – Nikolas

+0

動的な型のオブジェクトを返す必要があります。だからこそあなたはアロケータでそれを行います。 –

答えて

1

あなたはこれを間違った方法で行っていると思います。メタクラスを削除し、代わりにクラスとメソッドのデコレータを使用します。

@init_args_preprocessor 
def flat(operands, kwargs): # No need for asterisks 
    head = [] 
    for o in operands: 
     if isinstance(o, cls): 
      head += list(o.operands) 
     else: 
      head.append(o) 
    return tuple(head), kwargs 
クラスのデコレータにその機能を回すinit_args_preprocessorデコレータで

:今

def init_args_preprocessor(preprocessor): 
    def class_decorator(cls): 
     orig_init = cls.__init__ 
     def new_init(self, *args, **kwargs): 
      args, kwargs = preprocessor(args, kwargs) 
      orig_init(self, *args, **kwargs) 
     cls.__init__ = new_init 
     return cls 
    return class_decorator 

そして、代わりにミックスインデコレータを使用

たとえば、フラットとして定義

class Operation(object): 
    def __init__(self, *operands): 
     self.operands = operands 

@flat 
class F(Operation): 
    pass 

また、クラス修飾子を組み合わせても問題ありません

@init_args_preprocessor 
def orderless(args, kwargs): 
    return sorted(args), kwargs 

@orderless 
@flat 
class G(Expression): 
    pass 

警告:上記のすべてのコードは厳密にテストされていません。

+0

こんにちは、はい、とても良いソリューションのように見えます。この問題の1つの問題は、オブジェクト 'G'はクラスではなく関数であるため、isinstance()チェックはさらに微調整することなく失敗するということです。 – Nikolas

+1

'G'はなぜ機能していますか?これはクラスデコレータによってのみ変更されます。 '@ init_args_preprocessor'は' flat'をクラスをとり、クラスを返す関数に変換します。 –

+0

私の悪い、あなたは正しいです。これは、実際、私がやったのとまったく同じです。 – Nikolas

関連する問題