python解释器如何处理具有默认参数的函数定义的位置

Nan*_*Raj 11 python python-3.x

为什么第一个代码输出 51第二个代码输出 21。我理解第二个代码应该输出21,但我理解的方式,第一个代码也应该输出21(b的值变成20然后调用函数f)。我错过了什么?

b = 50

def f(a, b=b):
    return a + b

b = 20
print(f(1))
Run Code Online (Sandbox Code Playgroud)

输出:51

b = 50
b = 20

def f(a, b=b):
    return a + b
print(f(1))
Run Code Online (Sandbox Code Playgroud)

输出:21

编辑:这与如何更改 Python 2.7 中可选函数参数的默认值不同 因为这里讨论的是默认参数发生的无意变化,而不是如何有意更改默认参数的值,即这里的问题集中在python解释器如何处理具有默认参数的函数的函数定义位置。

San*_*iva 10

给 python 初学者的提示:如果你使用像 pycharm 这样的 IDE - 你可以放置一个调试器,看看变量发生了什么。

我们可以使用id(b)获取特定对象在内存中的地址来更好地理解正在发生的事情:

返回对象的“身份”。这是一个整数,保证在此对象的生命周期内是唯一且恒定的。生命周期不重叠的两个对象可能具有相同的 id()值。

CPython 实现细节:这是对象在内存中的地址。

让我将您的代码修改为以下内容:

b = 50
print("b=50 :", id(b))


def f(a, b=b):
    print("b in the function f :", id(b))
    print(id(b))
    return a + b


b = 20
print("b=20 :", id(b))
print(f(1))
Run Code Online (Sandbox Code Playgroud)

输出如下:

b=50 : 4528710960
b=20 : 4528710000
b in the function f : 4528710960
4528710960
51
Run Code Online (Sandbox Code Playgroud)

如您所见,b函数内部和它们b=50具有相同的地址。

当你做b=20一个新的对象被创建。

在 Python 中,(几乎)一切都是对象。在 Python 中我们通常所说的“变量”更恰当地称为名称。同样,“赋值”实际上是将名称绑定到对象。每个绑定都有一个定义其可见性的范围,通常是名称起源的块。

在蟒蛇中

当你做

b=50abindingb到 int 对象是在块的范围内创建

当我们稍后说b=20int 对象b=50不受影响时。这两者本质上是两个不同的对象。

您可以在这些链接中阅读更多相关信息。

  • 另外,在 python 中,默认参数仅计算一次(即在函数定义时)。Python 作为一种解释性语言,是逐行进行的。因此,在第一种情况下,“def f(a, b=b)”中的内部“b”将被“赋值”并引用该行的外部“b”值(即 50)。类似地,在第二种情况下,函数中的内部“b”将被分配该行外部“b”的值(即20) (2认同)