2012-01-22 10 views
3

私は、プロジェクトでしばしば再利用されるさまざまな関数のライブラリを構築しています。各関数はステートレスです(作成時にパラメータを必要とせず、メモリもありません)。一部の関数は他の関数を使用します。Python:ステートレス関数ライブラリの設計

これらの関数は、残りのプロジェクトで引数として渡されます。

次のアプローチのどちらが優れていますか?クラスのメソッドとして

def f1(x): 
    # use x 

def f2(x): 
    # use x and f1 

2.Defineすべての機能、および使用に基づく階層のクラスを配置:特定のモジュール内

1.Defineグローバル関数として全機能が

class F1: 
    def __call__(x): 
    # use x 

f1 = F1() 

class F2(F1): 
    def __call__(x): 
    # use x and f1 

f2 = F2() 

私がオプション2と考えた理由は、私の機能の中には共通のものがあるからです。たとえば、機能f2,f3,f11はすべてf1と呼びます。私は、内の任意の点を見ることができない、あなたはこれらのステートレス機能がある場合は、ではないでしょう、あなたのクラス、中のデータを保存していない場合

class F1: 
    def __call__(self, x): 
    self.f1(x) 
    self.calc(x) 
    def f1(self, x): 
    # do something 
    # don't define calc here; F1 is abstract base class 

class F2(F1): 
    def calc(self, x): 
    # do something 

class F3(F1): 
    def calc(self, x): 
    # do something 
+3

どこで2をするというアイディアを得ましたか? –

+0

@FrancisAvila:私の考えを説明するために更新された質問を見てください。 – max

+0

'F2'と' F3'は 'F1'を拡張することを意味しましたか?それはコードが言っているものではありません... –

答えて

2

オプション1はもっと簡単です。オプション2は不必要に複雑です!!

テストを容易にする別の提案:

1.1。それらをすべて1つのモジュール内の単一クラスのメソッドとして定義します。必要に応じて@staticmethodと@classmethodデコレータを使用してください。これにより、後で新しいクラスやサブクラスを提供することによって、モックの代替や代替実装によるオーバーライドを容易にすることができます。

spam.py:

class Spam(object): 
    @staticmethod 
    def f1(x): 
    # use x 

    @classmethod 
    def f2(cls, x): 
    # use x and cls.f1 

これには、あなたがちょうどあなたが上記のための必要を持ってまで、オプション1に固執することをお勧めしますがさらに複雑です。

+0

'@ classmethod'で提案しているものは、私が考えていたものに似ています。ある日、関数に状態を追加したいと思っていたので、すべてを '@ classmethod'にすることを強制したくありませんでした。とにかくクラスを書いているので、その潜在的な必要性に柔軟性を残すのはなぜですか? – max

+0

APIを変更せずに、状態を持つ必要がある場合は、クラスまたはオブジェクトで関数を置き換える方法があります。 – kindall

+0

@kindall:ああ、それは本当です。私はこれを考えなかった。それは非常に簡単です - ちょうど '__call__'を使用しますか? – max

2

:私はこのような何かをしたいと思うかもしれません考えていましたそれらを使用します。 Pythonではモジュールレベルで関数を正確に定義できるので、クラスの能力が本当に必要でない限り、クラスを使用する必要はありません。

3

最初と最後のどちらかで共通のコードを実行するためにいくつかの関数が必要な場合は、コモンコードをexplained hereのようにデコレータに置くことができます。