【问题标题】:flake8 complains on boolean comparison "==" in filter clauseflake8 抱怨过滤子句中的布尔比较“==”
【发布时间】:2013-09-25 06:44:56
【问题描述】:

我在 mysql 数据库表中有一个布尔字段。

# 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 的比较应该是“if cond is False:”或“if not 条件:"

好的,我认为这是有道理的。所以把我的代码改成这样:

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

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

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

【问题讨论】:

  • PEP 8 特别建议反对“如果 cond 为 False”。我很惊讶pep8 tool 的作用正好相反。

标签: python mysql sqlalchemy flake8


【解决方案1】:

这是因为 SQLAlchemy 过滤器是 == False 真正有意义的少数几个地方之一。 其他任何地方你都应该不要使用它。

# noqa 注释添加到该行并完成它。

或者你可以使用sqlalchemy.sql.expression.false:

from sqlalchemy.sql.expression import false

TestCase.obsoleted == false()

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

【讨论】:

    【解决方案2】:

    SQL Alchemy 还具有您可以使用的 is_isnot 函数。一个例子是

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

    More on those here

    【讨论】:

    • 在 Python 中 is== 是不同的,但我很确定这里生成的 SQL 将是相同的。
    • is== 在 SQLAlchemy 中是不同的,因为您不能在 python 中覆盖标识运算符 (is)。像Model.column is False 这样的表达式总是被评估为False,因为比较总是在python而不是数据库中立即发生。比较列对象和布尔值的标识的结果总是False。这会将 WHERE FALSEAND FALSE 之类的语句插入到您的查询中,在大多数情况下,无论如何都会导致它返回 0 行。
    【解决方案3】:

    我看看当==is_ 使用SQLAlchemy 时,当database dialect 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

    【讨论】:

    • 另外请注意,当您在 PostgreSQL 中使用 is 而不是 = 时,即使操作数为 NULL,您也永远不会得到 NULL 作为答案。如果任一操作数为 NULL,= 将返回 NULL。
    【解决方案4】:

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

    【讨论】:

    • # noqa 将禁用 整个 字符串的 flake8 / pep / other-linters,因此其他 linting-warnings 也将被忽略。其他答案提供了更好的解决方案,例如,.is_-method。
    【解决方案5】:

    你为什么不使用.filter_by(field=True) / .filter_by(field=False)

    【讨论】:

    • 如果您加入了表 filter_by,需要注意的一点可能是模棱两可的。
    【解决方案6】:
    caseNum = session.query(TestCase).filter(~TestCase.obsoleted).count()
    print(caseNum)
    

    works.try 在你的 sqlalchemy 版本中

    【讨论】:

      猜你喜欢
      • 2017-12-13
      • 1970-01-01
      • 2023-03-29
      • 1970-01-01
      • 2021-07-16
      • 2014-03-23
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多