函数定义在另一个函数定义中 - 慢?

发布于 2024-12-10 22:38:09 字数 403 浏览 0 评论 0原文

看看构建我的函数的两种方法:

class myClass:
    def _myFunc(self):
        pass

    def myFunc2(self):
        self._myFunc()

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

        myFunc()

第二个选项会更慢吗? 我只需要从 myFunc2 调用 myFunc,所以想从我的模块文档中隐藏它,我可以使用下划线,但我认为将它放在函数中会更干净。另一方面,我可能需要每秒调用 myFunc2 几百次,因此每次调用 myFunc2 时“重新定义”myFunc 可能会很慢......这是一个很好的猜测吗?

Look at two ways of structuring my functions:

class myClass:
    def _myFunc(self):
        pass

    def myFunc2(self):
        self._myFunc()

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

        myFunc()

Will the second option be slower?
I only need to call myFunc from myFunc2, so 'd like to hide it from my module documentation, I could use an underscore for that, but I thought it would be cleaner to have it inside the function. On the other hand I might need to call myFunc2 few hundred times per second, so "redefining" myFunc when calling myFunc2 each time might be slow... is that a good guess?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尽揽少女心 2024-12-17 22:38:09

在 64 位 Ubuntu 上使用 Python 2.6.5,没有明显的差异:

# 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

Using Python 2.6.5 on 64-bit Ubuntu, there is no discernible difference:

# 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
像你 2024-12-17 22:38:09

第二个变体中的本地函数不会被一遍又一遍地编译——它与整个文件一起编译一次,并且它的主体存储在代码对象中。在执行外部函数期间发生的唯一事情是代码对象被包装在一个新的函数对象中,然后该对象绑定到本地名称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()

对于上面的愚蠢代码,myClass.myFunc2()将立即返回,而myClass2.myFunc2()需要一秒钟才能执行。

The local function in the second variant won't be compiled over and over again -- it is compiled once together with the whole file, and its body is stored in a code object. The only thing that happens during the execution of the outer function is that the code object is wrapped in a new function object which is then bound to the local name myFunc.

There might be a difference between the two variants if myFunc() takes default parameters. Their definition would be executed over and over again in the second variant, resulting in a possible performance hit.

Exaggerated example:

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()

With the daft code above, myClass.myFunc2() will return immediately, while myClass2.myFunc2() takes a second to execute.

萌化 2024-12-17 22:38:09

点式查找(又名属性绑定)总是比嵌套范围查找花费更长的时间。前者涉及一系列查找字典和创建新对象(绑定或未绑定方法)。后者使用单元变量并使用数组查找来实现。

Dotted lookup (a.k.a. attribute binding) always takes longer than nested scope lookups. The former involves a series dictionary of lookups and creation of a new object (a bound or unbound method). The latter uses cell variables and are implemented using an array lookup.

坠似风落 2024-12-17 22:38:09

尽管其他答案声称没有效果,但我认为我应该检查一下。
我发现在外部定义函数有一个非常明显的优势。

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 毫秒

Despite the other answers that claim there is no effect, I thought I should check.
I found a very definite advantage to defining the function outside.

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 loops, best of 10: 4.2 ms per loop

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

10 loops, best of 10: 5.33 ms per loop

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

1 loops, best of 1: 438 ms per loop

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

1 loops, best of 1: 574 ms per loop

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文