在Python中通过引用与值传递
从 C++ 和Java等其他语言跳入Python编程的开发人员经常对Python中传递参数的过程感到困惑。以对象为中心的数据模型及其对分配的处理是基础层面混乱背后的原因。在下面的文章中,我们将讨论Python中传递参数的概念,并尝试借助示例来理解它。
Python参数传递模型是“按值传递”还是“按引用传递”?
提前阅读后,您可能想打点东西,所以要振作起来。 Python 的参数传递模型既不是“按值传递”也不是“按引用传递”,而是“按对象引用传递”。
“按值传递”、“按引用传递”和“按对象引用传递”的范例可以通过探索下面的示例函数来理解。
查看下面定义的两个函数:
def set_list(list):
list = ["A", "B", "C"]
return list
def add(list):
list.append("D")
return list
my_list = ["E"]
print(set_list(my_list))
print(add(my_list))
输出:
['A', 'B', 'C']
['E', 'D']
现在,让我们探索上面的代码,
变量不是传递的对象:
如果我告诉你《罗摩衍那》不是图尔西·达斯写的,而是《罗摩衍那》是由一个名叫图尔西·达斯的人写的。这种区别有意义吗?没有权利?!。但根据Python ,它确实如此,并且它做出了至关重要的区别。因此,在Python及其 PKD 中,事物与我们用来指代事物的标签之间存在很大差异。 “一个名叫 Tulsi Das 的人”只是一个人,“Tulsi Das”是用来指代那个人的名字。
所以,考虑一个列表
a = ["X", "Y"]
这里“a”是一个变量,指向一个包含元素“X”和“Y”的列表。但是“a”本身并不是列表。将“a”视为包含对象“X”和“Y”的存储桶。
通过参考:
通过引用传递变量(存储桶)直接传递给函数。该变量充当一个带有它的内容(对象)的包。
在上面的代码图像中,“list”和“my_list”都是同一个容器变量,因此指的是内存中完全相同的对象。函数对变量或对象执行的任何操作都会直接反映给函数调用者。例如,该函数可以完全改变变量的内容,并将其指向一个完全不同的对象:
此外,该函数可以重新分配变量的内容,效果如下:
总而言之,通过引用传递函数和调用者使用相同的变量和对象。
按值传递:
在按值传递中,函数提供了调用者传递给它的参数对象的副本。这意味着原始对象保持不变,并且所做的所有更改都是相同的副本并存储在不同的内存位置。
函数对变量或对象执行的任何操作也是如此
总结一下,函数调用者上下文中的变量和对象的副本是完全隔离的。
通过引用传递对象:
由于Python在此上下文中有所不同,因此Python中的函数接收调用者引用的内存中相同对象的引用。但是,该函数没有接收到调用者存储相同对象的变量(存储桶);与按值传递一样,该函数提供自己的存储桶并为自己创建一个全新的变量。
内存中的同一个对象被调用者和函数引用,所以当 append函数向列表中添加一个额外的元素时,调用者对象也会被更新。它们有不同的名称,但它们是同一个东西。两个变量都包含相同的对象。这就是通过对象引用传递的含义。函数和调用者在内存中使用相同的对象,但是通过不同的变量来获取它们。对函数变量(bucket)所做的任何更改都不会改变调用者变量(bucket)的性质,只会更新内容。
参考: Python是按引用传递还是按值传递?罗伯特·希顿