3

我正在使用 pdb 调试程序。我连续点击'c'来运行代码,并且在每一步pdb都会告诉我执行了哪一行。

假设我们有以下代码:

def foo(bar):
   print(bar)

foo('hey')

首先,第 4 行调用函数 foo。然后 pdb 向我展示了这条线

def foo(bar)

被执行。

为什么?那条线不只是一种标签吗?在执行“print(bar)”之前会发生什么?(伴随着另一个“命中”)

编辑:我尝试过实际检查定义。事实上,在 foo 是一个生成器(不能以这种方式调用)的情况下,python 仍然到达那里,然后决定将其视为一个生成器(或视情况而定的函数......)。

4

2 回答 2

8

def不是 Python 中的声明,而是可执行语句。在运行时,它检索为函数编译的代码对象,将其包装在动态创建的函数对象中,并将结果绑定到def. 例如,考虑这个无用的代码:

import dis
def f():
    def g():
        return 1
dis.dis(f)

这是输出的一部分(此处为 Python 2.7.5):

0 LOAD_CONST               1 (<code object g at 02852338, file ...>)
3 MAKE_FUNCTION            0
6 STORE_FAST               0 (g)

所有这一切通常都是一个不可见的细节,但你可以用它玩一些不起眼的把戏;-) 例如,想想这段代码做了什么:

fs = []
for i in range(3):
    def f(arg=i**3):
        return arg
    fs.append(f)
print [f() for f in fs]

这是输出:

[0, 1, 8]

这是因为可执行文件def创建了三个不同的函数对象,每次循环一个。非常有趣 :-)

于 2013-09-13T03:28:13.230 回答
1

在执行“print(bar)”之前会发生什么?

这只是一个有根据的猜测:我想当前 IP 被推入堆栈,然后是参数。然后创建一个新的堆栈帧,从堆栈中弹出参数并作为局部变量添加到当前范围。沿着这条线的东西。

于 2013-09-13T01:36:56.813 回答