Вопрос-Ответ

Is it Pythonic to use list comprehensions for just side effects?

По-питоновски ли использовать понимание списков только для побочных эффектов?

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

def fun_with_side_effects(x):
...side effects...
return y

Теперь, по-питоновски ли использовать понимание списков для вызова этой функции:

[fun_with_side_effects(x) for x in y if (...conditions...)]

Обратите внимание, что я нигде не сохраняю список

Или я должен называть эту функцию следующим образом:

for x in y:
if (...conditions...):
fun_with_side_effects(x)

Что лучше и почему?

Переведено автоматически
Ответ 1

Это очень антипитоновски, и любой опытный питонист устроит вам разнос из-за этого. Промежуточный список выбрасывается после его создания, и потенциально он может быть очень, очень большим и, следовательно, дорогостоящим в создании.

Ответ 2

Вам не следует использовать понимание списка, потому что, как говорили люди, это приведет к созданию большого временного списка, который вам не нужен. Следующие два метода эквивалентны:

consume(side_effects(x) for x in xs)

for x in xs:
side_effects(x)

с определением consume из itertools справочной страницы:

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)
python