简体   繁体   English

python 解释器如何处理具有默认参数的 function 定义的 position

[英]how python interpreter treats the position of the function definition having default parameter

Why the first code outputs 51 and the second code outputs 21 .为什么第一个代码输出51第二个代码输出21 I understand the second code should output 21, but the way I understood, the first code should also output 21 (The value of b changed to 20 and then is calling the function f).我理解第二个代码应该是output 21,但是按照我的理解,第一个代码应该也是output 21(b的值变成20然后是调用ZC1C425268E68385D1AB5074FC)。 What am I missing?我错过了什么?

b = 50

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

b = 20
print(f(1))

Output: 51 Output:51

b = 50
b = 20

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

Output: 21 Output:21

Edit: This is different from How to change default value of optional function parameter in Python 2.7?编辑:这与如何在 Python 2.7 中更改可选 function 参数的默认值不同? because here the unintentional change happening to the default parameter is being discussed, not how to intentionally change the value of default parameter, ie here the question focuses on how the python interpreter treats the position of function definition for functions having default parameters.因为这里讨论的是对默认参数的无意更改,而不是如何有意更改默认参数的值,即这里的问题集中在 python 解释器如何处理 ZC1C425268E68385D1AB5074F 的 position 定义具有默认参数的函数的 position。

Tip for python beginners : If you use IDEs like pycharm - you can put a debugger and see what is happening with the variables. python 初学者的提示:如果您使用像 pycharm 这样的 IDE - 您可以放置一个调试器并查看变量发生了什么。

We can get a better understanding of what is going on using the id(b) which gets us the address of the particular object in memory:我们可以使用id(b)更好地理解发生了什么,它为我们提供了 memory 中特定 object 的地址:

Return the “identity” of an object.返回 object 的“身份”。 This is an integer which is guaranteed to be unique and constant for this object during its lifetime.这是一个 integer,保证在此 object 在其生命周期内是唯一且恒定的。 Two objects with non-overlapping lifetimes may have the same id() value.具有非重叠生命周期的两个对象可能具有相同的id()值。

CPython implementation detail: This is the address of the object in memory. CPython实现细节:这是memory中object的地址。

Let me modify your code to the following:让我将您的代码修改为以下内容:

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))

The output is as following: output如下:

b=50 : 4528710960
b=20 : 4528710000
b in the function f : 4528710960
4528710960
51

As you can see the b inside the function and the b=50 have the same address.如您所见,function 中的bb=50具有相同的地址。

When you do b=20 a new object was created.当您执行b=20时,会创建一个新的 object。

In Python, (almost) everything is an object.在 Python 中,(几乎)一切都是 object。 What we commonly refer to as "variables" in Python are more properly called names.我们在 Python 中通常所说的“变量”更恰当地称为名称。 Likewise, "assignment" is really the binding of a name to an object.同样,“赋值”实际上是将名称绑定到 object。 Each binding has a scope that defines its visibility, usually the block in which the name originates.每个绑定都有一个 scope 定义其可见性,通常是名称起源的块。

In python在 python

When you do当你这样做

b=50 a binding of b to an int object is created in the scope of the block b=50 a binding b到 int object在块的 scope中创建

When we later say b=20 the int object b=50 is unaffected.当我们稍后说b=20时, int object b=50不受影响。 These both are essentially two different objects.这两者本质上是两个不同的对象。

You can read more about it in these links.您可以在这些链接中阅读有关它的更多信息。

Think of how the interpreter treats this.想想口译员是如何处理这个问题的。 In the first case, def f(a, b=b) is interpreted as def f(a, b=50) since the value of b in the current scope is 50 .在第一种情况下, def f(a, b=b)被解释为def f(a, b=50)因为当前 scope 中b的值为50 As such, f(1) assigns a to 1 , and thus, a + b = 1 + 50 = 51 .因此, f(1)a分配给1 ,因此a + b = 1 + 50 = 51

Similarly, in the second case, the value of b in the current scope is 20 when the function is declared, so the definition is interpreted as def f(a, b=20) .同样,在第二种情况下,当前 scope 中b的值在声明 function 时为 20,因此定义解释为def f(a, b=20) Therefore, f(1) = 21 .因此, f(1) = 21

The reason why the different placement of the function is resulting in different errors is because of the placement of the value 'b' as well. function 的不同放置导致不同错误的原因也是因为值“b”的放置。

Since the function 'f', is using a named parameter 'b', so it takes the first assignment of the variable 'b' as the argument/parameter to the function 'f'由于 function 'f' 使用命名参数 'b',因此它将变量 'b' 作为参数/参数的第一个赋值给 function 'f'

For example,例如,

b = 50

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

b = 20
print(f(1))

As you pointed out, this results in the output 51正如您所指出的,这导致 output 51

But if I were to change the code by a bit to但是,如果我将代码更改为

def f(a, b=b):
    return a + b
b = 50
b = 20
print(f(1))

It would result in the following error:这将导致以下错误:

def f(a, b=b):
NameError: name 'b' is not defined

Hence, we can deduce that the placement of the variable which is taken as a named parameter to the function is causing the difference in outputs.因此,我们可以推断出作为 function 的命名参数的变量的放置导致了输出的差异。

You can also use the global variables for the same.您也可以使用全局变量

Because by the time you are defining the function f in case 1, you are assigning the value of b (at that time it's 50 ) to the second argument of the function.因为当您在案例 1 中定义 function f时,您正在将b的值(当时为50 )分配给 function 的第二个参数。

While in case 2, at the time of assigning the value of b to the second argument of f it is 20 .而在情况 2 中,在将b的值分配给f的第二个参数时,它是20

This is the reason for the different answers in both cases.这就是两种情况下答案不同的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM