Существуют ли какие-либо существенные различия (в производительности или иным образом) между следующими двумя способами получения списка результатов?
users: Sequence[User] = session.execute(select(User)).scalars().all()
users: Sequence[User] = list(session.execute(select(User)).scalars())
Второй мне кажется более питоническим и возможен, потому что ScalarResult
выполняет итерацию по своим строкам, поэтому вызов list(...scalars())
просто перебирает объект ScalarResult
. Однако, поскольку .all()
тоже существует, я предполагаю, что для этого должна быть какая-то причина, так что, может быть, более эффективно использовать .all()
?
Каковы различия между ними и что происходит за кулисами, что вызывает эту разницу?
Глядя на источник, кажется, что разница есть. Вызывая ScalarResult.all()
, он в конечном итоге вызывает ResultInternal._allrows() . Тем временем ScalarResult.__iter__()
(который list()
является внутренним вызовом) он в конечном итоге вызывает ResultInternal._iterator_getter().
Хотя на первый взгляд может показаться, что между этими методами много дублирования, есть одно ключевое отличие: .all()
извлекает результаты за один раз, а .__iter__()
передает результаты один за другим.
Метод итератора может быть полезен в тех случаях, когда вам может потребоваться короткое замыкание и вы знаете, что вам не нужен полный набор результатов. Но этот пример как бы растрачивает это.
Что касается производительности, между ними много слоев, поэтому их сложнее комментировать. Но с точки зрения использования SQLAlchemy я бы сказал, что .all()
предпочтительнее для этого варианта использования.
Вопросы и ответы на GitHub здесь