2013-12-11 3 views
5

Оговорка: это прямо вопрос для кода-игры в гольф, так что я знаю, что я спрашиваю, плохая практика в производствеИзменяя список с помощью добавления в течение списка понимания

Я пытаюсь изменить массив во время понимания списка, но по какой-то причине он висит, и я не знаю, почему и как это исправить.

Я имею дело со списком перечней неопределенной глубины и необходимости конденсировать их до плоского списка - for those curious its this question. Но на этом этапе давайте просто скажем, что мне нужен плоский список всех элементов в списке, и 0, если это список.

Нормальный метод перебора списка и, если его список добавить его до конца, так как:

for o in x: 
if type(o)==type([]):x+=o 
else:i+=o 
print i 

Я пытаюсь сократить этот список с помощью понимания, как так.

print sum([ 
[o,x.append(o) or 0][type(o)==type([])] 
for o in x 
])) 

Теперь, я не знаю List.append возвращает None, так чтобы гарантировать, что я получаю числовое значение, ленивые вычисления говорят, что я могу сделать x.append(o) or 0, и так как None является «falsy» будет evaulate второй части, а значение 0.

Но это не так. Если я положил x.append() в список по сравнению с x, он не сломался или не ошибся, или не возвратит итерационную ошибку, он просто зависает. Почему append Замораживание во время просмотра списка, но цикл for выше работает нормально?

редактировать: Для того, чтобы сохранить этот вопрос от удаления, я не ищу гольф советы (они очень познавательно, хотя), я искал ответ, почему код не работает, как я написал это.

+0

Не по теме для этого вопроса, но по оригинальной проблеме: не было бы проще сгладить вложенный итерабель в итератор (что вы можете сделать в 2-строчной функции в 3.3+, 3-строчной функции без, если вы не можете использовать сторонние модули, такие как 'more-itertools'), тогда просто напишите тривиальный код над этим итератором? – abarnert

+0

@abarnert 'from itertools import *' имеет длину 22 символа, тогда вам нужно вызвать фактический метод. Это довольно высокая цена за библиотеку. –

+0

'sum (map (lambda x: x% 2-.5, flatten (a)))' всего 37 символов. 22 + 1 + 37 = 60, что, безусловно, превосходит 73, что есть сейчас. – abarnert

ответ

8

or может быть ленивым, но определения списков не являются. Для каждого o в x, когда [o,x.append(o) or 0][type(o)==type([])] уродство оценивается, Python должен оценить [o,x.append(o) or 0], что означает оценку x.append(o) or 0, что означает, что o будет добавляться к x независимо от того, является ли это список. Таким образом, вы в конечном итоге с каждым элементом x приложенном к x, а затем они получают добавляется снова и снова и снова и OutOfMemoryError

+0

Я, должно быть, не ожидал достаточно долго, чтобы увидеть ошибку. чертежная доска Я думаю :( –

+1

@LegoStormtroopr: Если вы на 6 4-разрядный Python на платформе, которая по мере необходимости расширяет свопинг (как по умолчанию для ОС X, так и для Windows), ошибка может не появиться до тех пор, пока часы после смены подкачки ... – abarnert

3

насчет:

y = [element for element in x if type(element) != list or x.extend(element)] 

(обратите внимание, что extend будет выравниваться, а append будет добавьте только вложенный список в конец, unflattened).

+2

Почему бы просто не сделать 'type (element)! = List '? 'list' * - это тип' [] '. – mgilson

+0

Гм, верно! Я изменил код @ Lego и получил перенос ветра :) Спасибо! Исправленный! – Roberto

+0

Блестящая игра в гольф, но на самом деле он не отвечает на вопрос. Хотя, я не мог в хорошем сознании представить это как свое решение на вызов и предложить вам сделать это. –

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