8

私は sqlalchemy の ORM 機能を多用しているため、多くの場合、データベースから既にデータをロードしており、既にロードされている Python オブジェクトの条件をチェックしたり、計算を実行したりしたいと考えています。また、データベースに対して sql を実行する (データをまったくロードしない) ことでより適切に表現される、より多くのバッチ指向のタスクを実行したい/実行する必要があります。同じコードを使用して、両方の用途で同じ計算を表現したいと思います。これにより、データベース接続のために後方に曲げたり、各計算を 2 回 (通常の Python で 1 回、再度クエリとして) 記述したり、実行したりする必要がなくなります。彼らが同意しないリスクがあります。

私が持っているとします:

from sqlalchemy import Integer, Column
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    bar = Column(Integer)

bool_clause = Foo.bar > 10
int_clause = Foo.bar + 10

a_foo = Foo(bar=5)

入手方法はありますか

>>> something(bool_clause, a_foo)
False
>>> something(int_clause, a_foo)
15

a_foo最初にデータベースに永続化してからクエリを実行することなく? データベースクエリのコンテキストでも使用できるように句を表現する方法が特に必要ですが、データベースクエリがなくても役立ちます。

1 つのオプションは、句を関数に変更することです。

bool_clause = lambda foo=Foo: foo.bar > 10
int_clause = lambda foo=Foo: foo.bar + 10
>>> bool_clause(a_foo)
False
>>> int_clause(a_foo)
15

しかし、これは節が表現された元の方法よりも読みにくいと思います。

4

1 に答える 1

6

この種のアプローチにはいくつかの方法があります。

1 つの方法は正面から、SQLAlchemy には Query.update() および Query.delete() メソッドで使用されるモジュールがあり、これは sqlalchemy.orm.evaluator と呼ばれます。非常に限られた式演算子のセットのみを表現できます。

>>> from sqlalchemy.orm.evaluator import EvaluatorCompiler
>>> print EvaluatorCompiler().process(bool_clause)(a_foo)
False
>>> print EvaluatorCompiler().process(int_clause)(a_foo)
15

などのより複雑な式は実行しませんがin_()、貢献したい場合は、このモジュールに合理的な操作をいくつでも追加できます。

ユースケースが通常行われる方法は、ハイブリッドのプロパティとメソッドを使用することです。この使用例では、 を持っているときにとを<anything>.someattr <some operator> <somethingelse>入れ替えることができるという点で、Python の優れた機能を利用しています。したがって、あなたの例は次のようになります。selfcls<anything>

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    bar = Column(Integer)

    @hybrid_method
    def bool_clause(self, other):
        return self.bar > other

    @hybrid_method
    def int_clause(self, other):
        return self.bar + other

>>> a_foo = Foo(bar=5)
>>> print a_foo.bool_clause(10)
False
>>> print a_foo.int_clause(10)
15

これは実際には、ラムダを使用するという提案と同じアイデアを使用していますが、よりうまく表現されています。

2 つのアプローチを組み合わせることもできます。エバリュエーターの優れた点の 1 つは、or_()や などの接続詞を処理できることand_()です。これがないと、「and」や「or」などを使用する必要がある場合、ハイブリッドではメソッドを「インスタンス」メソッドと「式」メソッドに分割する必要があります。

于 2013-01-12T20:13:04.553 に答える