определение функции внутри другого определения функции -slow? - PullRequest
6 голосов
/ 19 октября 2011

Посмотрите на два способа структурирования моих функций:

class myClass:
    def _myFunc(self):
        pass

    def myFunc2(self):
        self._myFunc()

class myClass:
    def myFunc2(self):
        def myFunc():
            pass

        myFunc()

Будет ли второй вариант медленнее? Мне нужно всего лишь вызвать myFunc из myFunc2, поэтому я хотел бы скрыть его от документации моего модуля, для этого я мог бы использовать подчеркивание, но я подумал, что было бы чище поместить его в функцию. С другой стороны, мне может понадобиться вызывать myFunc2 несколько сотен раз в секунду, поэтому «переопределение» myFunc при вызове myFunc2 каждый раз может быть медленным ... это правильное предположение?

Ответы [ 4 ]

7 голосов
/ 19 октября 2011

При использовании Python 2.6.5 на 64-битной Ubuntu нет заметной разницы:

# version 1
In [2]: %timeit c1.myFunc2()
1000000 loops, best of 3: 461 ns per loop

# version 2
In [3]: %timeit c2.myFunc2()
1000000 loops, best of 3: 464 ns per loop
3 голосов
/ 19 октября 2011

Локальная функция во втором варианте не будет компилироваться снова и снова - она ​​компилируется один раз вместе со всем файлом, а ее тело сохраняется в объекте кода.Единственное, что происходит во время выполнения внешней функции, это то, что объект кода обернут в новый объект функции, который затем привязывается к локальному имени myFunc.

. Между этими двумя понятиями может быть разницаварианты, если myFunc() принимает параметры по умолчанию.Их определение будет выполняться снова и снова во втором варианте, что приведет к возможному падению производительности.

Преувеличенный пример:

from time import sleep

class MyClass:
    def _my_func(self, x=sleep(1)):
        pass
    def my_func2(self):
        self._my_func()

class MyClass2:
    def my_func2(self):
        def my_func(x=sleep(1)):
            pass
        my_func()

С приведенным выше кодом daft, myClass.myFunc2() вернетнемедленно, в то время как myClass2.myFunc2() занимает секунду для выполнения.

2 голосов
/ 19 октября 2011

Поиск с точками (связывание атрибутов) всегда занимает больше времени, чем поиск с вложенными областями.Первый включает в себя последовательный словарь поиска и создания нового объекта (связанный или несвязанный метод).Последний использует переменные ячейки и реализуется с использованием поиска в массиве.

0 голосов
/ 07 июля 2016

Несмотря на другие ответы, которые утверждают, что никакого эффекта нет, я подумал, что должен проверить.Я нашел очень определенное преимущество для определения функции снаружи.

import random
def ff1(i):
    r1 = random.random()
    r2 = random.random()
    if r1 < 0.5:
        return i*r2
    else:
        return i/r2

def f1(i):
    return ff1(i)

def f2(i):
    def ff2(i):
        r1 = random.random()
        r2 = random.random()
        if r1 < 0.5:
            return i*r2
        else:
            return i/r2
    return ff2(i)
%%timeit -r 10 -n 10 
x = 0.5
for i in xrange(10000):
    x = f1(x)

10 циклов, лучшее из 10: 4,2 мс на цикл

%%timeit -r 10 -n 10
x = 0.5
for i in xrange(10000):
    x = f2(x)

10 циклов, лучшее из 10: 5,33 мс на цикл

%%timeit -r 1 -n 1 
x = 0.5
for i in xrange(1000000):
    x = f1(x)

1 циклов, лучшее из 1: 438 мс на цикл

%%timeit -r 1 -n 1
x = 0.5
for i in xrange(1000000):
    x = f2(x)

1 циклов, лучшее из 1: 574 мс на цикл

...