【问题标题】:python what happens when a function is called?python调用函数时会发生什么?
【发布时间】:2013-09-17 13:27:46
【问题描述】:

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

假设我们有这个代码:

def foo(bar):
   print(bar)

foo('hey')

首先,第 4 行调用函数 foo。然后 pdb 向我显示该行

def foo(bar)

被执行。

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

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

【问题讨论】:

  • 好问题!我期待着阅读答案。不过,我想说的是,如果它确实跳过了,那就更令人惊讶了。它还能如何验证参数等? (如果它跳过,如果你打电话给foo(1, 2),它怎么知道抱怨?)
  • 是的,但我需要确切地知道那里发生了什么。您@rogaos 可能是对的。但是,如果您建议 pdb 在 foo(1,2) 处停止执行并且永远不会到达 def 行。因此,当我们看到 def 行时,它已经接受/匹配了该函数。请注意,下一个's'命中到达打印行,并且一如既往地在执行该行之前停止。因此,您可以在函数发生任何事情之前检查堆栈/堆。

标签: python python-2.7 pdb


【解决方案1】:

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 创建了三个不同的函数对象,每次循环一个。很有趣:-)

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 听起来很合理。现在,我正面临一种特殊情况,即函数的 def 行出现问题。程序到达那里并且..不执行该功能!只有使用 pdb 我才注意到消息“GeneratorExit:None”。那么,您猜猜这一步会出现什么问题?请注意,我正在尝试制作一个最小的示例来重现它,同时它本身似乎是一个有趣的问题,我发布了它。
    • 所以,事实证明我的不是经典函数。因此,它在那里做的一件事就是检查它是什么。 stackoverflow.com/questions/18777544/…
    猜你喜欢
    • 2014-11-11
    • 2018-07-23
    • 2011-06-19
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    相关资源
    最近更新 更多