Как оптимизировать условные списки python

Я читал о List comprehension без [] в Python, поэтому теперь я знаю, что

''.join([str(x) for x in mylist])

быстрее, чем

''.join(str(x) for x in mylist)

потому что "понимание списков сильно оптимизировано"

Поэтому я полагаю, что оптимизация основана на анализе выражения for, видит mylist, вычисляет его длину и использует его для предварительного выделения точного размера массива, что экономит много перераспределения.

При использовании ''.join(str(x) for x in mylist), join получает генератор вслепую и должен строить свой список, не зная заранее размер.

Но теперь рассмотрим это:

mylist = [1,2,5,6,3,4,5]
''.join([str(x) for x in mylist if x < 4])

Как python определяет размер понимания списка? Вычисляется ли он из размера mylist и сокращается, когда итерации выполняются (что может быть очень плохо, если список большой, а условие отфильтровывает 99% элементов), или оно возвращается обратно к "дону", t знать размер заранее "случае?

EDIT: Я сделал несколько небольших тестов и, похоже, подтвердил, что существует оптимизация:

без условия:

import timeit

print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234]])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234])"))

дает (как и ожидалось):

3.11010817019474
3.3457350077491026

с условием:

print(timeit.timeit("''.join([str(x) for x in [1,5,6,3,5,23,334,23234] if x < 50])"))
print(timeit.timeit("''.join(str(x) for x in [1,5,6,3,5,23,334,23234] if x < 50)"))

дает:

2.7942209702566965
3.0316467566203276

поэтому условный listcomp все еще быстрее.

Ответ 1

Признаки списков не предваряют размер списка, даже если они полностью могут. Вы предполагаете наличие оптимизации, которая на самом деле не выполняется.

Понимание списка происходит быстрее, потому что все механизмы итератора и работа входа и выхода из фрейма стека genexp имеют стоимость. Понимание списка не требует оплаты этой стоимости.