Какой самый питонный способ выполнения выражения генератора? - PullRequest
3 голосов
/ 09 июля 2010

Все больше и больше функций Python становятся «ленивыми исполняемыми файлами», подобно выражениям генератора и иным видам итераторов.Иногда, однако, я вижу себя желающим накатить цикл «для» в одну строку, просто чтобы выполнить какое-то действие.

Что было бы наиболее питоническим, чтобы фактически выполнить цикл?

Например:

a = open("numbers.txt", "w")
(a.write ("%d " % i) for i in xrange(100))
a.close()

Не актуальный код, но вы понимаете, о чем я.Если вместо этого я использую генератор списков, у меня будет побочный эффект создания списка N-длины, заполненного "None".

В настоящее время я использую выражение в качестве аргумента в вызове.«любому» или «всему».Но я хотел бы найти способ, который не зависел бы от результата выражения, выполненного в цикле - и «any», и «all» могут останавливаться в зависимости от вычисляемого выражения.

Для ясности, этиЕсть способы сделать это, о которых я уже знаю, и у каждого есть свои недостатки:

[a.write ("%d " % i) for i in xrange(100))]

any((a.write ("%d " % i) for i in xrange(100)))

for item in (a.write ("%d " % i) for i in xrange(100)): pass

Ответы [ 3 ]

10 голосов
/ 09 июля 2010

Есть один очевидный способ сделать это, и именно так вы должны это сделать.Нет оправдания для того, чтобы сделать это умным способом.

a = open("numbers.txt", "w")
for i in xrange(100):
    a.write("%d " % i)
d.close()

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

В этом случае вам не нужно ленивое выполнение.Вы хотите казни.Вы можете просто ... выполнить.С петлей for.

7 голосов
/ 09 июля 2010

Если бы я хотел сделать этот конкретный пример, я написал бы

for i in xrange(100): a.write('%d ' % i)

Если бы мне часто приходилось использовать итератор для его эффекта, я бы определил

def for_effect(iterable):
    for _ in iterable:
        pass
5 голосов
/ 09 июля 2010

Есть много accumulators, которые в результате потребляют всю итерацию, которую им дают, например, min или max - но даже они не полностью игнорируют результаты, полученные в процессе (*Например, 1004 * и max вызовут исключение, если некоторые результаты являются комплексными числами).Я не думаю, что есть встроенный аккумулятор, который делает именно то, что вы хотите - вам придется написать (и добавить в свой личный тайник крошечную служебную функцию) крошечную служебную функцию, такую ​​как

def consume(iterable):
    for item in iterable: pass

Основная причина, я полагаю, заключается в том, что в Python есть оператор for, и вы должны использовать его, когда он подходит как перчатка (т. Е. Для случаев, для которых вы хотите consume; ;).

Кстати, a.write возвращает None, что является ложным, так что any будет фактически потреблять его (а a.writelines будет еще лучше!).Но я понимаю, что вы просто привели это в пример; -).

...