我广泛使用sqlalchemy中的ORM设施,因此在许多情况下,我已经从数据库加载了数据,并且想要检查条件或对已经加载的python对象执行计算; 我还希望/需要做更多面向批处理的任务,通过对数据库执行sql(而不是根本不加载数据)可以更好地表达这些任务.我想使用相同的代码来表达两种用途的相同计算,这样我就不必向后弯曲数据库连接或者每次计算两次(一次在常规python中,再次作为查询)并运行他们不同意的风险.
假设我有:
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)
Run Code Online (Sandbox Code Playgroud)
有办法得到
>>> something(bool_clause, a_foo)
False
>>> something(int_clause, a_foo)
15
Run Code Online (Sandbox Code Playgroud)
没有先坚持a_foo到数据库然后执行查询?我特别想要一种表达子句的方法,以便它也可以在数据库查询的上下文中使用,但是如果没有一个,它仍然有用.
一种选择是将条款更改为函数:
bool_clause = lambda foo=Foo: foo.bar > 10
int_clause = lambda foo=Foo: foo.bar + 10
Run Code Online (Sandbox Code Playgroud)
>>> bool_clause(a_foo)
False
>>> int_clause(a_foo)
15
Run Code Online (Sandbox Code Playgroud)
但我发现这比表达条款的原始方式更不易读.
有几种方法可以接近这种事情.
一种方法是,在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
Run Code Online (Sandbox Code Playgroud)
它不会执行更复杂的表达式,in_()但是如果您想要贡献,我们可以向此模块添加任意数量的合理操作.
现在,您使用的用例通常是使用混合属性和方法.在这个用例中,我们采取的Python在迷死的优势,当我们有<anything>.someattr <some operator> <somethingelse>,我们可以换出self和cls为<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
Run Code Online (Sandbox Code Playgroud)
这实际上是使用与你使用lambdas的建议相同的想法,只是表达得更好.
这两种方法也可以结合起来.评估者的一个好处是它处理像or_()和的连词and_().如果没有这个,混合体需要您将方法分解为"实例"和"表达式"方法,如果您需要使用"和"或"或"之类的东西.
| 归档时间: |
|
| 查看次数: |
694 次 |
| 最近记录: |