记录一个python的坑,调试的时候发现打印出来的变量和自己想象中的值不太一样,发现是Python引用的问题。
python并不刻意区分“按值传递”和“按引用传递”。
在底层,python将值分为不可变对象(比如int,str),和可变对象(比如列表list)。所有的变量都是对某个对象的引用,赋值(=)和函数参数传递,都将改变变量所引用的对象。
对于不可变对象int,str,赋值和传参将导致新创建对象,这和C++的引用行为是不同的。此时,赋值和传参是按值传递。
对于可变对象list,赋值和传参,和C++引用的行为一致,是真正的按引用传递。
python中的“引用”和C++的引用 - 千岛寒流 - 博客园 (cnblogs.com)
举个例子:
# 对于不可变对象(按值传递的感觉)
def modify_value(x):
x = 20
a = 10
modify_value(a)
print(a) # 输出 10,因为不可变对象在函数中重新赋值时,不影响原始变量
# 对于可变对象(按引用传递的感觉)
def modify_list(lst):
lst.append(4)
my_list = [1, 2, 3]
modify_list(my_list)
print(my_list) # 输出 [1, 2, 3, 4],因为可变对象在函数中被修改时,影响原始对象
在 Python 中,没有引用传递和按值传递的明确区分,而是根据对象的可变性来决定行为。
在 Python 中,函数参数的传递是通过对象的引用来进行的。当传递不可变对象时,类似于按值传递的效果,因为函数内部无法修改原始对象。
而对于可变对象,函数内部的修改会影响原始对象,类似于按引用传递的效果。
相较之下,C++ 显式区分了按值传递和引用传递。在 C++ 中,可以使用引用(Reference)来实现引用传递,或者直接使用值传递。在 C++ 中,引用传递需要显式地声明引用类型,而值传递则是默认的行为。
int类型这种不可变对象,在python中类似值传递,所以函数里面修改了值,函数外面还是不变的,就会和想象的不一样。
如果想在函数内部修改不可变对象的值,并且希望这些修改能够在函数外部生效,常见的处理是返回修改后的值并将其重新赋值给原始变量。
比如下面的处理:
def modify_value(x):
x = 20
return x
a = 10
a = modify_value(a) # 将函数返回的值重新赋值给变量 a
print(a) # 输出 20
另一种方式是使用可变对象,如列表,将值存储在列表中,并将列表传递给函数。因为列表是可变的,所以可以在函数内部修改列表的元素,会影响到原始列表。