Выбор между len()
и count()
зависит от ситуации, и стоит глубоко понять, как они работают, чтобы использовать их правильно.
Позвольте предложить вам несколько сценариев:
(наиболее важно) Если вы хотите знать только количество элементов и не планируете их обрабатывать каким-либо образом, важно использовать count()
:
DO: queryset.count()
- это будет выполнять один SELECT COUNT(*) some_table
запрос, все вычисления выполняются на стороне СУБД, Python просто нужно получить номер результата с фиксированной стоимостью O (1)
НЕ: len(queryset)
- это будет выполнять SELECT * FROM some_table
запрос, извлекая всю таблицу O (N) и требуя дополнительной памяти O (N) для ее хранения. Это худшее, что можно сделать
Когда вы все равно собираетесь получить набор len()
запросов, лучше использовать, что не приведет к дополнительному запросу к базе данных, как это count()
было бы:
len(queryset)
for obj in queryset:
pass
Количество:
queryset.count()
for obj in queryset:
pass
Отмененный 2-й случай (когда набор запросов уже был получен):
for obj in queryset:
len(queryset)
queryset.count()
len(queryset)
queryset.count()
Все станет ясно, если заглянуть «под капот»:
class QuerySet(object):
def __init__(self, model=None, query=None, using=None, hints=None):
self._result_cache = None
def __len__(self):
self._fetch_all()
return len(self._result_cache)
def _fetch_all(self):
if self._result_cache is None:
self._result_cache = list(self.iterator())
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()
def count(self):
if self._result_cache is not None:
return len(self._result_cache)
return self.query.get_count(using=self.db)
Хорошие ссылки в документации Django: