Установка локальных переменных для функции вместо использования глобальных переменных оптимизирует функцию - PullRequest
4 голосов
/ 17 июля 2011

В документации по модулю itertools я нашел этот комментарий

def dotproduct(vec1, vec2):
    return sum(imap(operator.mul, vec1, vec2))

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

def dotproduct(vec1, vec2, sum=sum, imap=imap, mul=operator.mul):
    return sum(imap(mul, vec1, vec2))

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

Редактировать: Я проверил с помощью timeit, и естьлюбая существенная разница.
Для двух списков из 40 элементов, таких как vec1, vec2:

глобальный поиск -> 3.22720959404
локальный поиск -> 3.19884065683

,есть только ок.1% прирост.

1 Ответ

2 голосов
/ 17 июля 2011

Есть ли практическое заметное ускорение (которое могло бы уравновесить неудобство большой сигнатуры функции)?

Я очень сомневаюсь в этом, так как поиск происходит один раз воригинальное определение.Обратите внимание, что вы изменили значение функции.

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

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

>>> def dotproduct(vec1, vec2):
...     return sum(imap(operator.mul, vec1, vec2))
...
>>> dis.dis(dotproduct)
  2           0 LOAD_GLOBAL              0 (sum)
              3 LOAD_GLOBAL              1 (imap)
              6 LOAD_GLOBAL              2 (operator)
              9 LOAD_ATTR                3 (mul)
             12 LOAD_FAST                0 (vec1)
             15 LOAD_FAST                1 (vec2)
             18 CALL_FUNCTION            3
             21 CALL_FUNCTION            1
             24 RETURN_VALUE
>>> def dotproduct(vec1, vec2, sum=sum, imap=imap, mul=operator.mul):
...     return sum(imap(mul, vec1, vec2))
...
>>> dis.dis(dotproduct)
  2           0 LOAD_FAST                2 (sum)
              3 LOAD_FAST                3 (imap)
              6 LOAD_FAST                4 (mul)
              9 LOAD_FAST                0 (vec1)
             12 LOAD_FAST                1 (vec2)
             15 CALL_FUNCTION            3
             18 CALL_FUNCTION            1
             21 RETURN_VALUE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...