python中的值传递和引用传递
Python中的变量是没有类型的,我们可以把它看做一个(*void)类型的指针,变量是可以指向任何对象的,而对象才是有类型的。
Python中的对象有可变对象(number,string,tuple等)和不可变对象之分(list,dict等)。
值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(被调函数新开辟内存空间存放的是实参的副本值)
引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。(被调函数新开辟内存空间存放的是实参的地址)
1. 不可变对象作为函数参数,相当于C语言的值传递。
1 def test(c): 2 print("test before ") 3 print(id(c)) #一开始传递进来的是对不可变数据类型a(数字类型)的引用 4 c += 2 #数字改变后有一个新的指针指向3所在内存空间,但原来指向2的指针a(内存地址空间依旧存在)未改变 5 print("test after ") 6 print(id(c)) #故c的内存地址改变 7 return c 8 9 10 if __name__ == "__main__": 11 a = 2 12 print(id(a)) 13 n = test(a) #4 14 print(a) #2 15 print(id(a))
1 最终 2 输出的值为 3 1547916096 4 test before 5 1547916096 6 test after 7 1547916160 8 2 9 1547916096
2. 可变对象作为函数参数,相当于C语言的引用传递。(因列表是可变数据类型,作为参数传递实则是传递对列表的引用,修改更新列表值后依旧引用不变)
1 def test(list2): 2 print("test before ") 3 print(id(list2)) #221 4 list2[1] = 30 5 print("test after ") 6 print(id(list2)) #221 7 return list2 8 9 if __name__ == "__main__": 10 list1 = ["loleina", 25, 'female'] 11 print(id(list1)) #221 12 list3 = test(list1) 13 print(list1) #["loleina",30, 'female'] 14 print(id(list1)) #221 15 print(id(list3))
1 17192136 2 test before 3 17192136 4 test after 5 17192136 6 ['loleina', 30, 'female'] 7 17192136 8 17192136