gpt4 book ai didi

Python:为什么 int 和 list 函数参数的处理方式不同?

转载 作者:行者123 更新时间:2023-12-01 04:58:35 24 4
gpt4 key购买 nike

我们都知道全局变量不好的教条。当我开始学习 python 时,我读到传递给函数的参数被视为函数内部的局部变量。这似乎至少是事实的一半:

def f(i):
print("Calling f(i)...")
print("id(i): {}\n".format(id(i)))
print("Inside f(): i += 1")
i += 1
print("id(i): {}".format(id(i)))
return

i = 1
print("\nBefore function call...")
print("id(i): {}\n".format(id(i)))
f(i)

其计算结果为:

Before function call...
id(i): 507107200

Calling f(i)...
id(i): 507107200

Inside f(): i += 1
id(i): 507107232

据我所知,Python中函数的调用机制是“通过对象引用调用”。这意味着参数最初是通过其对象引用传递的,但如果在函数内部修改它,则会创建一个对象变量。在我看来,这似乎是合理的,可以避免函数无意修改全局变量的设计。

但是如果我们传递一个列表作为参数会发生什么?

def g(l):
print("Calling f(l)...")
print("id(l): {}\n".format(id(l)))
print("Inside f(): l[0] += 1")
l[0] += 1
print("id(l): {}".format(id(l)))
return

l = [1, 2, 3]
print("\nBefore function call...")
print("id(l): {}\n".format(id(l)))
g(l)

这会导致:

Before function call...
id(l): 120724616

Calling f(l)...
id(l): 120724616

Inside f(): l[0] += 1
id(l): 120724616

正如我们所看到的,对象引用保持不变!所以我们处理一个全局变量,不是吗?

我知道我们可以通过将列表的副本传递给函数来轻松克服这个问题:

g(l[:])

但我的问题是:Python 中函数参数实现两种不同行为的原因是什么?如果我们打算操作全局变量,我们也可以使用“global”关键字来表示列表,就像我们对整数所做的那样,不是吗?这种行为如何符合Python的禅宗“显式优于隐式”?

最佳答案

Python 有两种类型的对象 - 可变对象和不可变对象(immutable对象)。大多数内置类型,如 int、string 或 float,都是不可变的。这意味着他们无法改变。像列表、字典或数组这样的类型是可变的,这意味着它们的状态可以改变。几乎所有用户定义的对象也是可变的。

当您执行i += 1时,您为i分配了一个新值,即i + 1。这不会以任何方式改变 i,它只是说它应该忘记 i 并将其替换为 i + 1 的值。然后i被一个全新的对象所取代。但是,当您在列表中执行 i[0] += 1 时,您对列表说应该将元素 0 替换为 i[0] + 1。这意味着 id(i[0]) 将随着新对象而更改,并且列表 i 的状态将更改,但它的标识保持不变 - 它与原来的对象相同,只是发生了变化。

请注意,在 Python 中,字符串并非如此,因为它们是不可变的,更改一个元素将复制具有更新值的字符串并创建新对象。

关于Python:为什么 int 和 list 函数参数的处理方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26797922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com