它不起作用的原因有多种:
首先,在函数中分配的对象是在本地创建的。当您执行a=... 和b=... 时,a 和b 是您在分配给参数值的函数中创建的本地 对象。一旦函数退出,a 和 b 就不再与立即函数范围之外的代码保持任何相关性。
其次,虽然对象在 Python 中在引用中传递,但保持不变的是不可变的。由于x 和y 是整数,因此它们是不可变的,即每次对它们执行任何操作时,都会为对象分配一个新值,而不是更改它。 p>
要理解这一点,请考虑以下函数:
def mod_lists(list_1, list_2, list_3):
print("obj ID of rlst_1 = {0}\n"
"obj ID of rlst_2 = {1}\n"
"obj ID of rlst_3 = {2}\n".format(id(rlst_1), id(rlst_2), id(rlst_3)))
print("Before change:\n"
"obj ID of list_1 = {0}\n"
"obj ID of list_2 = {1}\n"
"obj ID of list_3 = {2}\n".format(id(list_1), id(list_2), id(list_3)))
list_1.append("hello")
list_2 = list_1 + ["world"]
list_3 = list_1 + ["world"]
print("After change:\n"
"obj ID of list_1 = {0}\n"
"obj ID of list_2 = {1}\n"
"obj ID of list_3 = {2}\n".format(id(list_1), id(list_2), id(list_3)))
return list_3
现在考虑我想通过三个lists:
rlst_1 = list()
rlst_2 = list()
rlst_3 = list()
我调用函数如下:
rlst_3 = mod_lists(rlst_1, rlst_2, rlst_3)
现在您可能会期待rlst_1 = ['hello']、rlst_2 = ['hello', 'world'] 和rlst_3 = ['hello', 'world'],但这是错误的。如果您运行它,您会注意到rlst_2 实际上是一个空的list(未更改)。
那么是什么让rlst_1 和rlst_3 发生了变化?让我们看一下打印出来的对象ID并进行比较:
# NOTE: You will see different numbers on your system.
obj ID of rlst_1 = 52178816
obj ID of rlst_2 = 52337240
obj ID of rlst_3 = 51607312
Before change:
obj ID of list_1 = 52178816
obj ID of list_2 = 52337240
obj ID of list_3 = 51607312
After change:
obj ID of list_1 = 52178816
obj ID of list_2 = 52336920
obj ID of list_3 = 52336840
在对函数进行任何更改之前,您可以看到对象 ID 完全相同分别相同,这意味着 list_1 是 rlst_1 的精确引用等。现在在changes were done 是您注意到更改的地方。您可以看到 list_2 和 list_3 现在有不同的对象 ID。这是为什么?这是因为在list_2=... 和list_3=... 行中,您实际上重新分配这两个对象到一个新引用,即list_1 + ['world']。您可能还想知道为什么它们都有不同的 ID,因为值应该相同。虽然list_1 是同一个引用,但每个['world'] 都是list 对象的新实例,其中包含单词"world" 作为一个项目,因此它们是不同的对象,即使它们具有相同的值。
为什么list_1 的对象引用不受影响?这是因为当您在 list_1 上调用 append 函数时,它不会重新分配,而是更改引用中的对象,将值 "hello" 附加到同一个对象中。
现在在函数调用之后,当你打印rlsts 时,你会看到:
# rlst_1
# ['hello']
# rlst_2
# []
# rlst_3
# ['hello', 'world']
rlst_1 已按预期更改,因为引用中的同一对象已被修改。 rlst_2 没有改变,因为即使 list_2 被重新分配了一个新列表,它也是一个在函数内创建的本地对象,并在函数退出后丢失。
为什么rlst_3 会更新?您可能认为它已更新,但它实际上是一个具有相同名称的 NEW 对象。注意函数的最后一部分返回本地创建的list_3,其值为list_1 + ['world']。所以函数调用的计算如下:
rlst_3 = mod_lists(rlst_1, rlst_2, rlst_3)
(local) list_1 = ['hello']
(local) list_3 = list_1 + ['world']
(local) list_3 = ['hello', 'world']
rlst_3 = list_3
rlst_3 = ['hello', 'world']
如果这仍然令人困惑,请运行 id(rlst_3),您将看到 52336840,这正是本地创建的 list_3 的对象 ID(同样,您可能会看到不同的数字,但id(rlst_3) 将始终等于id(list_3))。
应用这个逻辑,现在你可以理解为什么不能在引用中传递不可变整数并希望在函数中修改它们。更改外部对象的唯一方法是将它们重新分配给函数返回的新创建的本地对象。
这个答案显然比 Stephen Rauch 的要啰嗦得多,但它提供了更多关于为什么它不起作用的背景。