Python:经常调用函数

时间:2018-02-02 15:24:11

标签: python performance encapsulation

我有这个Python 3伪代码:

def f1():
    a, b, c, d, e, f = some_other_fn()
    if (condition):
        f2(a, b, c, d, e, f)

def f2(a, b, c, d, e, f):
    complex_set_of_operations_with(a, b, c, d, e, f)

for i in range(1000):
    f(1)

现在,我对f2()中的长签名和重复感到恼火,并希望将其封装到f1()中:

def f1():
    def f2():
        complex_set_of_operations_with(a, b, c, d, e, f)

    a, b, c, d, e, f = some_other_fn()
    if (condition):
        f2()

for i in range(1000):
    f(1)

现在,我的问题是:如果我运行f1()一千次,那么解释器是否必须解析f2()一千次,或者它是否足够聪明以获得可重复使用的引用?

感谢。

2 个答案:

答案 0 :(得分:4)

让我们看一下(使用Python 3.5,我碰巧在手边)。我们将使用dis模块来反汇编函数并检查其字节码:

>>> def f1():
...     def f2():
...         complex_set_of_operations_with(a, b, c, d, e, f)
...     a, b, c, d, e, f = some_other_fn()
...     if (condition):
...         f2()
... 
>>> import dis
>>> dis.dis(f1)
  2           0 LOAD_CLOSURE             0 (a)
              3 LOAD_CLOSURE             1 (b)
              6 LOAD_CLOSURE             2 (c)
              9 LOAD_CLOSURE             3 (d)
             12 LOAD_CLOSURE             4 (e)
             15 LOAD_CLOSURE             5 (f)
             18 BUILD_TUPLE              6
             21 LOAD_CONST               1 (<code object f2 at 0x7f5d58589e40, file "<stdin>", line 2>)
             24 LOAD_CONST               2 ('f1.<locals>.f2')
             27 MAKE_CLOSURE             0
             30 STORE_FAST               0 (f2)
             ...  # the rest is omitted for brevity

在运行时,Python解释器逐个解释这些原始字节码指令。这些说明在documentation

中有说明

正如上面示例中的最后四条指令所示,Python确实每次构建内部函数(并将其存储在名称f2下),但它似乎通过加载预编译常量来有效地执行此操作f221 LOAD_CONST)行的代码对象,即它不会一遍又一遍地编译f2的正文。

答案 1 :(得分:-1)

Python评估很懒惰。只有在实际需要时才会对其进行评估。

https://swizec.com/blog/python-and-lazy-evaluation/swizec/5148

Lazy evaluation python