2009-11-23 5 views
0

У меня есть набор функций:Эффективный способ вызова набор функций в Python

functions=set(...) 

Все функции нужно один параметр х.

Что наиболее эффективный способ в Python сделать что-то похожее на:

for function in functions: 
    function(x) 
+8

Что не так с кодом, который у вас там есть? – 2009-11-23 20:54:23

+0

Если правила для создания набора разрешены, у меня возникнет соблазн написать функцию отправки, которая сделает соответствующие вызовы упорядоченными. Это более явный подход. –

+0

См. Также: http://stackoverflow.com/questions/897362/what-is-the-idiomatic-way-of-invoking-a-list-of-functions-in-python – Stephan202

ответ

7

Код отдаешь,

for function in functions: 
    function(x) 

... похоже, не делать ничего с результатом вызова function(x). Если это действительно так, то есть эти функции призваны к их побочным эффектам, то нет больше альтернативы питонов. Просто оставьте свой код таким, какой он есть.& dagger; Точка взять домой здесь, в частности, является

                                                            Избегайте функций с побочными эффектами в списках.

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

>>> timeit.Timer('[f(20) for f in functions]', 'functions = [lambda n: i * n for i in range(100)]').repeat() 
[44.727972984313965, 44.752119779586792, 44.577917814254761] 
>>> timeit.Timer('for f in functions: f(20)', 'functions = [lambda n: i * n for i in range(100)]').repeat() 
[40.320928812026978, 40.491761207580566, 40.303879022598267] 

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


  & кинжалом;: Ну, я бы написал for f in functions, так что разница между function и functions более выражена. Но об этом не говорит.

+3

+1 для напоминания «Избегайте функций с помощью побочных эффектов в списках-напоминаниях». –

+0

Тем более, что порядок итерации по заданным членам не определен – Ber

1

Если вам нужен выход, список понимание будет работать.

[func(x) for func in functions] 
0

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

[func(x) for func in functions] 

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

В любом случае, убедитесь, что вы прокомментируете свой код, чтобы подтвердить, что это действительно узкое место, которое вам необходимо позаботиться.

+0

Нет никакой особой причины, чтобы понимание списка должен быть быстрее, чем цикл 'for'. Такие требования требуют контрольных показателей. –

+0

http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Loops, похоже, указывает на то, что существует определенная причина, а именно, что цикл вставляется в скомпилированный код C. Правда, есть и другие факторы, которые также способствуют, поэтому я сказал ему профиль. – Epcylon

0

Edit: я переделал тест с использованием timeit

Мой новый тестовый код:

import timeit 

def func(i): 
    return i; 

a = b = c = d = e = f = func 

functions = [a, b, c, d, e, f] 

timer = timeit.Timer("[f(2) for f in functions]", "from __main__ import functions") 
print (timer.repeat()) 

timer = timeit.Timer("map(lambda f: f(2), functions)", "from __main__ import functions") 
print (timer.repeat()) 

timer = timeit.Timer("for f in functions: f(2)", "from __main__ import functions") 
print (timer.repeat()) 

Вот результаты этого времени.

testing list comprehension 
[1.7169530391693115, 1.7683839797973633, 1.7840299606323242] 

testing map(f, l) 
[2.5285000801086426, 2.5957231521606445, 2.6551258563995361]  

testing plain loop 
[1.1665718555450439, 1.1711149215698242, 1.1652190685272217] 

Мой оригинал, time.time() таймингов на основе довольно много рядный с этим тестирования, простой для петель, как представляется, является наиболее эффективным.

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