每次调用其父函数时,是否都会重新定义内部函数?

Are inner functions redefined every time their parent function is called?

提问人:pilu 提问时间:4/3/2020 更新时间:4/3/2020 访问量:933

问:

我知道 Python 中的函数是一等公民,这意味着它们是类的对象,类似于类的对象。这意味着在它们生命周期中的某个时刻,会调用构造函数。对于大多数函数,我希望在定义它们时发生这种情况(因为大多数函数可能只定义一次),因此无论我们使用多少次,我们都只支付一次构建价格。function5int

但是嵌套函数呢?每次调用其父级时,都会重新定义这些内容。这是否意味着我们每次都要重新构建对象?如果是,那不是效率低下吗?私有方法(假设父函数是方法)或其他函数不是更有效率吗?我忽略了支持嵌套的讨论范围界定论点。

我运行了一个简单的实验,它似乎支持我前面提到的论点,因为内部函数版本较慢:

import time

def f(x, y):
    def defined_inside(x, y):
        return x + y
    return defined_inside(x, y)

def defined_outside(x, y):
    return x + y

def g(x, y):
    return defined_outside(x, y)

start = time.time()
for i in range(10000000):
    _ = f(3, 4)
end = time.time()

print("Using inner function it took {} seconds".format(end - start))

start = time.time()
for i in range(10000000):
    _ = g(3, 4)
end = time.time()

print("Using outer function it took {} seconds".format(end - start))

结果:

Using inner function it took 2.494696855545044 seconds
Using outer function it took 1.8862690925598145 seconds

奖励问题:如果上述情况属实,那么这种情况与编译语言(如 Scala)有什么关系?我成长为嵌套和高阶函数的巨大乐趣,如果这个技巧像看起来那样低效,那就太可怕了。

Python Scala 嵌套

评论

2赞 Mark 4/3/2020
如果要嵌套函数,通常希望它创建一个新对象。例如,您经常这样做是为了从父级捕获闭包。这只有在每个内部功能都是新创建的时才有效。
4赞 martineau 4/3/2020
是的,它们每次都会被重新创建。
0赞 hl037_ 8/5/2023
@Mark捕获闭包不需要重新创建对象,而只需要存储具有不同绑定的执行上下文,这就是其他语言中使用的。

答: 暂无答案