Есть ли карта без результата в python?

Иногда я просто хочу выполнить функцию для списка записей – например:

for x in wowList: installWow(x, 'installed by me') 

Иногда мне нужен этот материал для инициализации модуля, поэтому я не хочу иметь такой размер, как x в глобальном пространстве имен. Одним из решений было бы просто использовать карту вместе с лямбдой:

 map(lambda x: installWow(x, 'installed by me'), wowList) 

Но это, конечно, создает хороший список [None, None, …], так что мой вопрос в том, есть ли подобная функция без возвращаемого списка – так как мне это просто не нужно.

(конечно, я тоже могу использовать _x и, таким образом, не оставлять видимых следов, но картографическое решение выглядит так аккуратно …)

12 Solutions collect form web for “Есть ли карта без результата в python?”

Вы можете использовать фильтр и функцию, которая не возвращает значение True. Вы получите пустой список возврата, так как фильтр добавляет только значения, которые оцениваются как true, что, я полагаю, спасет вам некоторую память. Что-то вроде этого:

 #!/usr/bin/env python y = 0 def myfunction(x): global y y += x input = (1, 2, 3, 4) print "Filter output: %s" % repr(filter(myfunction, input)) print "Side effect result: %d" % y 

Выполнение этого результата производит:

 Filter output: () Side effect result: 10 

Вы можете создать свою собственную «каждую» функцию:

def each(fn, items): for item in items: fn(item) # called thus each(lambda x: installWow(x, 'installed by me'), wowList)
def each(fn, items): for item in items: fn(item) # called thus each(lambda x: installWow(x, 'installed by me'), wowList) 

В основном это просто карта, но без возвращаемых результатов. Используя функцию, вы убедитесь, что переменная «item» не течет в текущую область.

Как насчет этого?

 for x in wowList: installWow(x, 'installed by me') del x 

Каждое выражение оценивает что-то, поэтому вы всегда получаете результат, независимо от того, как вы это делаете. И любой такой возвращенный объект (точно так же, как ваш список) впоследствии будет выброшен, потому что больше нет ссылки на него.

Чтобы прояснить: очень немного вещей в python – это утверждения, которые ничего не возвращают. Даже вызов функции

 doSomething() 

все равно возвращает значение, даже если оно сразу же отбрасывается. В python нет никакой функции, как функция / процедура Pascal.

Вы можете попробовать следующее:

 filter(lambda x: installWow(x, 'installed by me') and False, wowList) 

Таким образом, результат возврата – это пустой список, несмотря ни на что.

Или вы можете просто отказаться от and False если вы можете заставить installWow() всегда возвращать False (или 0 или None или другое выражение, которое оценивает false).

если это нормально, чтобы разбить wowList

 while wowList: installWow(wowList.pop(), 'installed by me') 

если вы хотите сохранить wowList

 wowListR = wowList[:] while wowListR: installWow(wowListR.pop(), 'installed by me') 

и если вопросы порядка

 wowListR = wowList[:]; wowListR.reverse() while wowListR: installWow(wowListR.pop(), 'installed by me') 

Хотя в качестве решения головоломки мне нравится первый 🙂

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

 reduce(lambda x,y: x(y, 'installed by me') , wowList, installWow) 

только твист устанавливается. Вернемся, например,

 def installWow(*args): print args return installWow 

сначала перепишем цикл for как выражение генератора, который не выделяет никакой памяти.

 (installWow(x, 'installed by me') for x in wowList ) 

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

 ( [1, installWow(x, 'installed by me')][0] for x in wowList ) 

который создает список, но возвращает только константу 1. это можно удобно использовать с reduce

 reduce(sum, ( [1, installWow(x, 'installed by me')][0] for x in wowList )) 

Который удобно возвращает количество элементов в wowList, которые были затронуты.

Просто сделайте installWow return None или сделайте последнее утверждение таким:

 def installWow(item, phrase='installed by me'): print phrase pass 

и используйте это:

 list(x for x in wowList if installWow(x)) 

x не будет задано в глобальном пространстве имен, а возвращаемый список – [] a singleton

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

 reduce(lambda _x: installWow(_x, 'installed by me'), wowList, None) 

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

Читайте дальше, если основной проблемой является оптимизация:

Еще три пути, потенциально быстрее, чем другие, описанные здесь:

  1. Для Python> = 2.7 используйте collections.deque ((installWow (x, 'установлен мной) для x в wowList), 0) # сохраняет 0 записей при повторении всего генератора, но да, все еще имеет побочный результат финального объект вместе с внутренней проверкой длины элемента
  2. Если вас беспокоит такой накладные расходы, установите cytoolz . Вы можете использовать счетчик, который по-прежнему имеет побочный результат приращения счетчика, но это может быть меньшее количество циклов, чем проверка на предмет, но не уверен. Вы можете использовать его вместо any () следующим образом:
  3. Замените выражение генератора на itertools.imap (когда installWow никогда не возвращает True. В противном случае вы можете рассмотреть itertools.ifilter и itertools.ifilterfalse с None для предиката): any (itertools.imap (installWow, wowList, itertools.repeat ('установлен меня')))

Но настоящая проблема заключается в том, что функция возвращает что-то, и вы не хотите, чтобы она возвращала что-либо. Поэтому, чтобы решить эту проблему, у вас есть 2 варианта. Один из них заключается в том, чтобы реорганизовать ваш код, поэтому installWow принимает в wowList и выполняет итерацию внутри него. Другой – скорее раздумья, но вы можете загрузить функцию installWow () в скомпилированный аст, например:

 lines,lineno=inspect.getsourcelines(func) # func here is installWow without the parens return ast.parse(join(l[4:] for l in lines if l)) # assumes the installWow function is part of a class in a module file.. For a module-level function you would not need the l[4:] 

Затем вы можете сделать то же самое для внешней функции и пройти по аш, чтобы найти цикл for. Затем в теле цикла for вставьте элемент определения функции instalWow () функции ast, сопоставляя имена переменных. Затем вы можете просто вызвать exec на самом астрале и предоставить словарь пространств имен с нужными переменными. Чтобы убедиться, что ваши изменения в дереве верны, вы можете проверить, как выглядит конечный исходный код, запустив astunparse .

И если этого недостаточно, вы можете перейти на cython и написать файл .pyx, который будет генерировать и компилировать файл .c в библиотеку с привязками python. Затем, по крайней мере, потерянные циклы не будут потрачены на преобразование в объекты python и обратно, а также проверку типов все раз.

Я проверил несколько разных вариантов, и вот результаты, которые я получил.

Python 2:

 >>> timeit.timeit('for x in xrange(100): L.append(x)', 'L = []') 14.9432640076 >>> timeit.timeit('[x for x in xrange(100) if L.append(x) and False]', 'L = []') 16.7011508942 >>> timeit.timeit('next((x for x in xrange(100) if L.append(x) and False), None)', 'L = []') 15.5235641003 >>> timeit.timeit('any(L.append(x) and False for x in xrange(100))', 'L = []') 20.9048290253 >>> timeit.timeit('filter(lambda x: L.append(x) and False, xrange(100))', 'L = []') 27.8524758816 

Python 3:

 >>> timeit.timeit('for x in range(100): L.append(x)', 'L = []') 13.719769178002025 >>> timeit.timeit('[x for x in range(100) if L.append(x) and False]', 'L = []') 15.041426660001889 >>> timeit.timeit('next((x for x in range(100) if L.append(x) and False), None)', 'L = []') 15.448063717998593 >>> timeit.timeit('any(L.append(x) and False for x in range(100))', 'L = []') 22.087335471998813 >>> timeit.timeit('next(filter(lambda x: L.append(x) and False, range(100)), None)', 'L = []') 36.72446593800123 

Обратите внимание, что значения времени не так точны (например, относительная производительность первых трех вариантов варьировалась от запуска до запуска). Мой вывод состоит в том, что вы должны просто использовать цикл, он более читабельный и выполняет, по крайней мере, так же, как и альтернативы. Если вы хотите избежать загрязнения пространства имен, просто del переменную после ее использования.

Interesting Posts

Почему datetime.datetime.utcnow () не содержит информацию о часовом поясе?

Раскрасить изображение, сохраняя прозрачность с помощью PIL?

Регрессионная регрессия панд: альтернативы циклу

Рисование средней строки в гистограмме (matplotlib)

Разделение словаря / списка внутри столбца Pandas в отдельные столбцы

Как получить звуковой конверт с помощью python?

re.findall, который возвращает dict названных групп захвата?

Ошибка при использовании knnMatch с OpenCV + Python

Окна TKinter не отображаются при использовании многопроцессорности в Linux

Дискретное трансверсальное преобразование Фурье из списка точек xy

В чем разница между плюсом и добавлением в python для манипулирования списками?

Почему эта переменная класса одинакова для разных экземпляров?

Regex работает неправильно, сопоставляя неожиданные вещи

Какая магия предотвращает блокировку программ Tkinter в интерактивной оболочке?

SSLError: сбой сброса оповещений sslv3

Python - лучший язык программирования в мире.