flake8抱怨filter子句中的布尔比较“ ==”


74

我在mysql db表中有一个布尔字段。

# table model
class TestCase(Base):
    __tablename__ = 'test_cases'
    ...
    obsoleted = Column('obsoleted',  Boolean)

要获得所有未过时的测试用例的计数,可以像这样简单地完成:

caseNum = session.query(TestCase).filter(TestCase.obsoleted == False).count()
print(caseNum)

效果很好,但是flake8报告以下警告:

E712:与False的比较应为“如果cond为False:”或“如果非cond:”

好吧,我认为这是有道理的。因此,将我的代码更改为此:

caseNum = session.query(TestCase).filter(TestCase.obsoleted is False).count()

要么

caseNum = session.query(TestCase).filter(not TestCase.obsoleted).count()

但是它们都不起作用。结果始终为0。我认为filter子句不支持运算符“ is”或“ is not”。有人可以告诉我如何处理这种情况。我不想禁用薄片。


PEP 8特别建议不要“如果cond为False”。我很惊讶pep8工具却相反。
Janne Karila 2013年

Answers:


90

这是因为SQLAlchemy过滤器是== False实际上有意义的少数几个位置之一。在其他地方,你应该使用它。

# noqa在该行中添加注释并完成操作。

或者您可以使用sqlalchemy.sql.expression.false

from sqlalchemy.sql.expression import false

TestCase.obsoleted == false()

其中,false()返回会话SQL方言的正确值。有一个匹配项sqlalchemy.expression.true


72

SQL炼金术也有is_isnot你可以使用的功能。一个例子是

Model.filter(Model.deleted.is_(False))

更多关于这里的


1
在Python中is==它们是不同的,但是我敢肯定,这里生成的SQL是相同的。
avoliva '16

1
is并且==在SQLAlchemy中有所不同,因为您无法在python中覆盖身份运算符(is)。之类的表达式Model.column is False之所以总是被求值,是False因为比较总是在python中而不是在数据库中立即进行。比较列对象和布尔值的标识的结果始终是False。这将在您的查询中插入类似WHERE FALSEAND FALSE的语句,无论哪种情况,在大多数情况下,这都会使其返回0行。
乔什(Josh)2013年

10

我看一下SQLAlchemy何时==以及is_何时将数据库方言Postgresql用于布尔字段会生成什么确切的查询:

  • 因为==我们得到:

    1. field == False 转换为 field = false
    2. field == True 转换为 field = true
    3. field == None 转换为 field IS NULL
  • 因为is_()我们得到:

    1. field.is_(False) 转换为 field IS false
    2. field.is_(True) 转换为 field IS true
    3. field.is_(None) 转换为 field IS NULL

注意: is_(not None)将评估is_(bool(not None)给予的价值is_(True)field = true因此您宁愿去isnot(None)生产 field IS NOT NULL


2
还要注意的是,当您使用is而不是=PostgreSQL时,即使操作数为NULL,也永远不会得到NULL作为答案。=如果任一操作数为NULL,则将返回NULL。
Jim Hunziker,

0

@Jruv# noqa在语句前面使用,它将忽略警告。


3
# noqa会为整个字符串禁用flake8 / pep / other-linters ,因此其他掉毛警告也将被忽略。其他答案提供了更好的解决方案,例如.is_-method。
maxkoryukov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.