参考资料:
1、Python值传递还是引用传递 https://blog.csdn.net/xinxin957_/article/details/81873074
示例:
代码一:
- list1 = ['a','b','c','d','e','f','g']
- num = len(list1)
- def func1(a,b):
- print(id(a),id(b))
- a.pop(0)
- b -= 1
- print(id(a),id(b))
- return
- print(list1,num)
- print(id(list1),id(num))
- func1(list1,num)
- print(list1,num)
- print(id(list1),id(num))
运行结果:
['a', 'b', 'c', 'd', 'e', 'f', 'g'] 7 # 变量list1和num的内容
3024548553288 140708972385504 # 变量list1所引用的内存 和 变量num所引用的内存
3024548553288 140708972385504 # 刚进入函数func1时,参数a和b的值是对list1和num的引用
3024548553288 140708972385472 # 因为list1是可变对象,对a进行a.pop(0)操作时,a所引用的内容就是list1的内容
# 因为num是不可变对象,在进行 b -= 1运算时,先把原来b引用的内容进行复制,b再引用新的内存
['b', 'c', 'd', 'e', 'f', 'g'] 7 # 函数执行完之后,list1改变,num没有改变
3024548553288 140708972385504 # 变量list1所引用的内存 和 变量num所引用的内存 都没有变化
代码二:
- A = 100
- B = A
- print(id(A),id(B))
- A -= 1
- print(id(A),id(B))
- print(A,B)
运行结果:
140708972388480 140708972388480 # A、B都引用相同的内存
140708972388448 140708972388480 # 对A 进行操作时,因为A是不可变对象,内存被2个变量引用,因此复制原对象内容后,把A指向新的对象,然后再对A应用的对象进行操作
99 100 # A的值改变,B因为还引用原来的对象,内容没有改变
代码三:
对本文开头的第二篇文章的引用进行说明
- def spam(eggs):
- print(id(eggs))
- eggs.append(1)
- print(id(eggs))
- eggs = [2, 3]
- print(id(eggs))
- ham = [0]
- print(id(ham))
- spam(ham)
- print(id(ham))
- print(ham)
运行结果:
2576493339208 # 变量ham引用对象的地址
2576493339208 # 刚进入函数时,参数eggs引用的相同的对象
2576493339208 # 因为 ham(eggs) 是list,为可变对象,对eggs引用的对象操作也是对ham引用的对象操作
2576493339272 # 重新对eggs赋值(引用新的对象),eggs为新的对象的地址
2576493339208 # ham 没有被重新赋值,所以引用的对象一直没有变
[0, 1] # ham 应用的对象在函数中被改变
总结:
Python中所有的变量都是对象(object),变量都是对象的引用(可以理解为对象的地址)。
Python中函数参数的传递是传引用的方式,传递参数时,是传递原参变量的引用(可以理解为传递原变量引用对象的地址)。
Python中把对象(Object)分为可变对象(list、dict、set等)和不可变对象(number、string、tuple等)。当在函数中对参数所引用的对象进行改变时,如果对象是可变对象,则直接进行对象内容的改变,反应到程序中,我们就看到了函数外的原来的参数被改变;如果对象是不可变对象时,则先在内存中复制一个对象的副本,参数引用同时改为指向这个副本,然后再对这个副本的内容进行操作,改变的是副本。见“代码一”。
如果多个变量引用同一个不可变对象时,当对一个变量的值进行改变时,先复制一个新的对象副本,再将变量指向新的对象副本,然后再进行改变对象的操作。见“代码二”。
如果多个变量引用同一个可变对象时,对其中一个变量重新赋值后,这个变量引用新的对象,其他变量还是引用原来的对象。见“代码三”函数中的eggs。