Подумайте о функции, которую я вызываю для нее побочные эффекты, а не возвращают значения (например, печать на экран, обновление GUI, печать в файл и т.д.).
def fun_with_side_effects(x):
...side effects...
return y
Теперь, это Pythonic, чтобы использовать списки, чтобы вызвать этот func:
[fun_with_side_effects(x) for x in y if (...conditions...)]
Обратите внимание, что я не сохраняю список в любом месте
Или мне следует называть это func следующим образом:
for x in y:
if (...conditions...):
fun_with_side_effects(x)
Что лучше и почему?
Ответ 1
Это очень анти-Pythonic, и любой опытный Pythonista даст вам черт возьми. Промежуточный список отбрасывается после его создания, и он потенциально может быть очень, очень большим и, следовательно, дорогостоящим для создания.
Ответ 2
Вы не должны использовать понимание списка, потому что, как сказали люди, вы создадите большой временный список, который вам не нужен. Следующие два метода эквивалентны:
consume(side_effects(x) for x in xs)
for x in xs:
side_effects(x)
с определением consume
на странице itertools
man:
def consume(iterator, n=None):
"Advance the iterator n-steps ahead. If n is none, consume entirely."
# Use functions that consume iterators at C speed.
if n is None:
# feed the entire iterator into a zero-length deque
collections.deque(iterator, maxlen=0)
else:
# advance to the empty slice starting at position n
next(islice(iterator, n, n), None)
Конечно, последнее понятно и понятнее.
Ответ 3
Смысл списка заключается в создании списков. И если вы на самом деле не создаете список, вы не должны использовать списки.
Итак, я получил бы второй вариант, просто перейдя по списку, а затем вызовет функцию, когда применяются условия.
Ответ 4
Во-вторых, лучше.
Подумайте о человеке, который должен понимать ваш код. Вы можете получить плохую карму легко с первой:)
Вы можете пойти посредине между ними, используя filter(). Рассмотрим пример:
y=[1,2,3,4,5,6]
def func(x):
print "call with %r"%x
for x in filter(lambda x: x>3, y):
func(x)
Ответ 5
Зависит от вашей цели.
Если вы пытаетесь выполнить некоторую операцию над каждым объектом в списке, необходимо принять второй подход.
Если вы пытаетесь создать список из другого списка, вы можете использовать понимание списка.
Явный лучше, чем неявный. Простой лучше, чем сложный. (Python Zen)
Ответ 6
Вы можете сделать
for z in (fun_with_side_effects(x) for x in y if (...conditions...)): pass
но это не очень красиво.
Ответ 7
Я бы сделал это вместо этого:
any(fun_with_side_effects(x) and False for x in y if (...conditions...))
Это выражение генератора и не генерирует случайный список, который отбрасывается. Я думаю, что это уродливо, и я бы не делал этого в коде. Но если вы настаиваете на том, чтобы реализовать свои циклы таким образом, как бы я это сделал.
Я склонен чувствовать, что понимание списков и их образ должны сигнализировать о попытке использовать что-то, по крайней мере слабо напоминающее функциональный стиль. Помещение вещей с побочными эффектами, которые нарушают это предположение, заставит людей читать ваш код более тщательно, и я думаю, что это плохо.