Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python sqlalchemy子句可以在没有数据库的情况下进行计算吗?_Python_Sqlalchemy - Fatal编程技术网

Python sqlalchemy子句可以在没有数据库的情况下进行计算吗?

Python sqlalchemy子句可以在没有数据库的情况下进行计算吗?,python,sqlalchemy,Python,Sqlalchemy,我在sqlalchemy中广泛使用ORM功能,因此在许多上下文中,我已经从数据库中加载了数据,并希望检查条件或对已经加载的python对象执行计算;我还希望/需要执行更多面向批处理的任务,这些任务通过对数据库执行sql(而不是加载数据)来更好地表达。我希望使用相同的代码来表示两种用途的相同计算,这样我就不必为了数据库连接而向后折腾,也不必为每个计算编写两次(一次在常规python中,另一次作为查询),并冒着它们不一致的风险 假设我有: from sqlalchemy import Integer

我在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)
有什么方法可以到达吗

>>> something(bool_clause, a_foo)
False
>>> something(int_clause, a_foo)
15
不先将a_foo持久化到数据库,然后执行查询?我特别想要一种表达子句的方法,这样它也可以在数据库查询的上下文中使用,但在没有查询的情况下仍然有用

一种选择是将条款改为职能:

bool_clause = lambda foo=Foo: foo.bar > 10
int_clause = lambda foo=Foo: foo.bar + 10

但是我发现这比最初表达这些子句的方式可读性差。

有几种方法可以解决这类问题

一种方法是正面的,Query.update()和Query.delete()方法使用SQLAlchemy中的一个模块,该模块称为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
它不会执行更复杂的表达式,例如中的
,但是,如果您愿意,我们愿意将任何数量的合理操作添加到此模块中

现在,您通常使用的用例是使用。在这个用例中,我们利用了Python的惊人之处,即当我们拥有
.someattr
时,我们可以将
self
cls
替换为
。你的例子是:

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
这实际上使用了与您建议使用lambdas相同的想法,只是表达得更为巧妙


这两种方法也可以结合使用。evaluator的一个优点是它处理诸如
之类的连词。如果没有这一点,如果需要使用诸如“and”或“or”或之类的内容,混合方法需要将方法分解为“instance”和“expression”方法。

您能给出一些上下文说明为什么要这样做吗?这当然回答了我提出的问题。我想避免把
Foo()
和太多的
hybrid.*
混在一起。有没有一种合理的方法可以将它们转移到另一个类/模块中,并且仍然希望它们能够工作?好吧,它们生成python描述符,这些描述符在类中最为常见。你已经在做的lambda方法基本上是一样的。OTOH EvaluatorCompiler是我多年没有看过的东西(其他人写的),但看起来有点整洁。哦,事实上,如果混乱是唯一的问题,我通常用mixin或抽象基类来做这种事情。像某个业务对象一样,它实现了多个mixin,这些mixin提供了一组混合体。我有一些有几十种逻辑方法。但最终还是会在类的命名空间上组装表达式。
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