问题描述
我有一个声明性基类 News
:
I have a declarative base class News
:
class News(Base):
__tablename__ = "news"
id = Column(Integer, primary_key = True)
title = Column(String)
author = Column(String)
url = Column(String)
comments = Column(Integer)
points = Column(Integer)
label = Column(String)
我还有一个函数 f(title)
,它获取一个字符串并返回字符串的 3 个变体之一:'good'、'maybe' 或 'never'.我尝试过滤行:
I also have a function f(title)
, that gets a string and returns one of 3 variants of strings: 'good', 'maybe' or 'never'.I try to get filtered rows:
rows = s.query(News).filter(News.label == None and f(News.title) == 'good').all()
但程序失败,引发此错误:
But the program fails, raising this error:
raise TypeError("Boolean value of this clause is not defined")
我该如何解决?
推荐答案
问题是这样的:
News.label == None and f(News.title) == 'good'
# ^^^ here
Python 不允许覆盖布尔操作and
和or
的行为.您可以使用 __bool__
在 Python 3 和 __nonzero__
在 Python 2 中,但它所做的只是定义对象的真值.
Python does not allow overriding the behaviour of boolean operations and
and or
. You can influence them to some extent with __bool__
in Python 3 and __nonzero__
in Python 2, but all that does is that it defines the truth value of your object.
如果有问题的对象没有实现 __bool__
并抛出错误,或者实现没有抛出,由于 and
和 或的短路特性
:
If the objects in question had not implemented __bool__
and thrown the error, or the implementation had not thrown, you would've gotten possibly rather cryptic errors due to the short-circuiting nature of and
and or
:
In [19]: (News.label == 'asdf') and True
Out[19]: <sqlalchemy.sql.elements.BinaryExpression object at 0x7f62c416fa58>
In [24]: (News.label == 'asdf') or True
Out[24]: True
因为
In [26]: bool(News.label == 'asdf')
Out[26]: False
这可能会导致以不正确的 SQL 表达式的形式拉扯头发:
This could and would lead to hair pulling in the form of incorrect SQL expressions:
In [28]: print(News.label == 'asdf' or News.author == 'NOT WHAT YOU EXPECTED')
news.author = :author_1
要生成布尔 SQL 表达式,请使用 and_()
, or_()
和 not_()
sql 表达式函数,或二进制 &
, |
和 ~
运算符重载:
To produce boolean SQL expressions either use the and_()
, or_()
, and not_()
sql expression functions, or the binary &
, |
, and ~
operator overloads:
# Parentheses required due to operator precedence
filter((News.label == None) & (f(News.title) == 'good'))
或
filter(and_(News.label == None, f(News.title) == 'good'))
或将多个条件传递给对 Query.filter()
:
or pass multiple criterion to a call to Query.filter()
:
filter(News.label == None, f(News.title) == 'good')
或组合多次调用filter()
:
filter(News.label == None).filter(f(News.title) == 'good')
这篇关于SQLAlchemy:使用`and` 和`or` 时出现意外结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!