2017-01-07 2 views
12

Я читал о List comprehension without [ ] in 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]) 

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

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

Ответит ли это на ваш вопрос: [Сводка списка по сравнению с результатами weird timeit в выражении генератора?] (Http://stackoverflow.com/questions/11964130/list-comprehension-vs-generator-expressions-weird-timeit-results) –

+0

неплохо, но в этом вопросе никогда не бывает условия _after_ цикла for. Только в самом выражении, что означает, что размер известен заранее. –

+1

Я думаю, что поведение в отношении того, как Python имеет дело с 'for x в xx для y в yy' при использовании связанного вопроса и' для x в y, если x <123' в вашем вопросе должно быть аналогичным, как в случае Python do не знать размер результирующего списка до тех пор, пока выражение не будет оценено. * (просто логическое предположение, не уверен, что это правда) * –

ответ

11

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

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

+0

еще одна загадка решена для меня. Благодарю. –

+2

Может ли быть значительный выигрыш в предопределении списка? Как отметил Жан-Франсуа, «это может быть плохо, если список большой, а условие отфильтровывает 99% элементов», но опять же, это может быть * хорошо *, если условие отфильтровано только 1% элементов ! – usr2564301

+0

@RadLexus точно: если повторная сборка является «списком» или чем-то с заранее известным размером и отсутствием условия, нет двойного цикла «для», это может быть особый случай (очень распространенный) для предварительного выделения размер списка. Будет применяться в 80% случаев в существующих кодах! –

Смежные вопросы