python试图理解调用堆栈

2024-04-19 07:02:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图理解下面代码的调用堆栈,但我无法回答

为什么此行返回4:

7. return z

为什么第5行是:

16 x = x + m1(x) 

希望你能帮助我

1  def m1(x): 
2      x = x + 1
3      z = m2(x, 4)
4      x = x + 1
5      z = z + 1
6      print(x)
7      return z
8 
9  def m2(x, y):
10     x = x + 1
11     y = y + 1
12     print(x, y)
13     return x
14
15 x = 1
16 x = x + m1(x)

Tags: 代码return堆栈defprintm1m2行是
2条回答

这是因为变量x和z是不可变的。
在python中,当我们将不可变的参数传递给函数时,引用调用就不再适用了。
一旦我们改变了这些变量的值,函数就会产生它自己的副本,即局部变量。这就是背后的原因。
Please refer this for more information

我想你需要知道的是函数内部的变量和函数外部的变量是不同的。或者更准确地说,每次调用一个函数时,只为该函数调用创建一组新的变量,而与任何其他可能具有相同名称的变量无关(所以,举个例子,如果你

def f1(x): 
    x = x + 1
    return x

x = 1
x = f1(x)
x = f1(x)
print(x)

实际上有三个独立的变量叫做x:一个位于顶层(“global”),它被初始化为1,一个是为第一次调用f1创建的,另一个是为第二次调用f1创建的。如果你给他们的名字加上注释以区别他们,那么实际上会发生以下情况:

x_global = 1

# Python does this behind the scenes
f1_call1_argument1 = x_global
# call f1
x_f1_call1 = f1_call1_argument1
# now your code in f1 starts running
x_f1_call1 = x_f1_call1 + 1
f1_call1_return_value = x_f1_call1
# return from f1
x_global = f1_call1_return_value

# now repeat but with the second call to f1
f1_call2_argument1 = x_global
x_f1_call2 = f1_call2_argument1
x_f1_call2 = x_f1_call2 + 1
f1_call2_return_value = x_f1_call2
x_global = f1_call2_return_value

print(x_global)

从这里你可以看到不同的变量是如何分开的,即使它们在代码中有相同的名称。每个变量都有自己的“区域”,其中名称表示该变量,而在不同的“区域”中,相同的名称表示不同的变量。这被称为scoping


我提到有些例外。这里有两个比较常见的例子:

  • Python允许您在函数内部放置一个“全局声明”,当您希望该名称引用函数内部与函数外部相同的内容时。如果我这样定义f2

    def f2():
        global x
        x = x + 1
        return x
    

    那么x就没有特定于函数的(“本地”)版本了。它将只使用全局x。运行此代码

    x = 1
    x = f2()
    x = f2()
    

    工作原理如下:

    x_global = 1
    
    # call f2
    x_global = x_global + 1
    f2_call1_return_value = x_global
    # return from f2
    x_global = f2_call1_return_value
    
    x_global = x_global + 1
    f2_call2_return_value = x_f1_call2
    x_global = f2_call2_return_value
    
  • 您还可以为参数设置一个默认值,并且由于Python实现方式中的设计决策,默认值有效地存储在一个不可见变量中,该变量在函数调用之间保持不变。如果我有

    def f3(x=[]):
        x.append(5)
        return x
    
    x = [1]
    x = f3()
    x = f3()
    

    (我使用列表是因为它可以更改,但整数不能更改)然后它的工作方式如下:

    # as part of the definition of f3
    f3_argument1_default = []
    
    x_global = [1]
    
    # first call to f3
    f3_call1_argument1 = f3_argument1_default
    x_f3_call1 = f3_call1_argument1
    x_f3_call1.append(5)                      # f3_argument1_default is now  [1,5]
    f3_call1_return_value = x_f3_call1
    x_global = f3_call1_return_value
    
    # second call to f3
    f3_call2_argument1 = f3_argument1_default
    x_f3_call2 = f3_call2_argument1
    x_f3_call2.append(5)                      # f3_argument1_default is now  [1,5,5]
    f3_call2_return_value = x_f3_call2
    x_global = f3_call2_return_value
    

相关问题 更多 >