4

SQLAlchemy がクエリ文字列を構築する方法は非常に興味深いと思います。

(Session.query(model.User)
        .filter(model.User.age > 18)
        .order_by(model.User.age)
        .all())

私が見る限り、ある種のProxy Patternが適用されています。私の小さなプロジェクトでは、OOP アプローチを使用して同様の文字列を作成する必要があります。そこで、この動作を再構成しようとしました。

最初に、いくつかの種類のオブジェクト、多くの同様のオブジェクトの 1 つ:

class SomeObject(object):
    items = None

    def __init__(self):
        self.items = []

    def __call__(self):
        return ' '.join(self.items) if self.items is not None else ''

    def a(self):
        self.items.append('a')
        return self

    def b(self):
        self.items.append('b')
        return self

このオブジェクトのすべてのメソッドはselfを返すため、任意の順序で無制限に呼び出すことができます。

2 つ目は、オブジェクトを呼び出して結果の文字列を表示するperformメソッドでない場合にサブジェクトのメソッドを呼び出すプロキシ オブジェクトです。

import operator

class Proxy(object):
    def __init__(self, some_object):
        self.some_object = some_object

    def __getattr__(self, name):
        self.method = operator.methodcaller(name)
        return self

    def __call__(self, *args, **kw):
        self.some_object = self.method(self.some_object, *args, **kw)
        return self

    def perform(self):
        return self.some_object()

そして最後に:

>>> obj = SomeObject()
>>> p = Proxy(obj)
>>> print p.a().a().b().perform()
a a b

この実装について何が言えますか? このような文字列を同じ構文で構造化するのに望ましい量のクラスを作成するより良い方法はありますか?

PS: 私の英語で申し訳ありませんが、それは私の母国語ではありません.

4

2 に答える 2

3

実際、あなたが見ているのはプロキシパターンではなくビルダーパターンです。はい、あなたの実装はIMHOが古典的なものです( Fluentインターフェースパターンを使用しています)。

于 2011-10-19T14:25:53.573 に答える
1

SQLAlchemy が何をするのかはわかりませんが、メソッドが 、などのメソッドを持つオブジェクトをSession.query()返すようにすることでインターフェイスを実装します。これらのメソッドはそれぞれ、適用された変更を考慮して新しいオブジェクトを返すだけです。これにより、最初の例のようにメソッドチェーンが可能になります。Queryfilter()order_by()all()Query

あなた自身のコード例には多くの問題があります。一例

obj = SomeObject()
p = Proxy(obj)
a = p.a
b = p.b
print a().perform()  # prints b
于 2011-10-19T14:17:36.757 に答える