【发布时间】:2021-01-06 19:30:13
【问题描述】:
我正在尝试将类型提示引入现有代码库,但在尝试键入查询时遇到了问题。
from sqlalchemy.orm.query import Query
class DbContext:
def __init__(self, db_host, db_port, db_name, db_user, db_password):
engine = create_engine(...)
session = sessionmaker(bind=engine)
self.Session: Session = session(bind=engine)
...
def fetch(context: DbContext, filters: ...):
sub_query: Query = context.Session.query(...)
在我添加类型提示之前,动态过滤只是一个简单的问题:
if filters.name is not None:
sub_query = sub_query.filter(
Person.name.ilike(f"%{filters.name}%"))
但是,现在提示我收到此错误:
类型“None”的表达式不能分配给声明的类型“Query”
果然filter似乎返回None:
(方法)过滤器:(*标准:未知)-> 无
我导航到the source,看来该方法确实没有返回任何内容。
def filter(self, *criterion):
for criterion in list(criterion):
criterion = expression._expression_literal_as_text(criterion)
criterion = self._adapt_clause(criterion, True, True)
if self._criterion is not None:
self._criterion = self._criterion & criterion
else:
self._criterion = criterion
显然某处存在断开连接,因为将 None 分配给 sub_query 应该会导致提示警告的错误,但我需要执行分配以使过滤真正起作用:
# Does NOT work, filtering is not applied
if filters.name is not None:
sub_query.filter(
Person.name.ilike(f"%{filters.name}%"))
# Works but Pylance complains
if filters.name is not None:
sub_query = sub_query.filter(
Person.name.ilike(f"%{filters.name}%"))
这是我第一次涉足 Python,希望得到一些关于这里发生了什么的指导!
【问题讨论】:
-
如果您谈论的是 PEP 484 支持,它还没有实现,因为到目前为止 SQLAlchemy 一直支持 Python 2.7。 SQLAlchemy 1.4 旨在促进从 SQLA 1.3 和 SQLA 2.0 的过渡,后者放弃了对 Python 2.7 的支持,很可能支持 PEP 484。
-
啊,很高兴知道。我只是摸不着头脑,
sub_query = sub_query.filter(...)似乎将None分配给sub_query,但这显然不会发生,因为随后对sub_query.filter的调用不会导致异常-顺便说一下代码正在运行,filter似乎正在返回Query -
Iirc
Query.filter用_generative装饰器装饰。它创建副本,将其传递给filter(),然后返回。就像“为什么有效”一样。既然你说你是 Python 新手,你可以在这里阅读装饰器:wiki.python.org/moin/PythonDecorators。 -
欣赏教育!
标签: python sqlalchemy type-hinting pylance pyright