python 函数中的参数传递

本文通过实验探讨了Python中参数传递的机制,分析了可变类型(如列表、字典、集合)与不可变类型(如数字、字符串、元组)在函数调用中的行为差异,并解释了内存地址传递及引用计数机制。

学习 Python 中,对 Python 中的参数传递存有疑惑,想知道传递的是一份拷贝还是引用地址,于是测试一番。
个人理解,如有误请指出。

测试

print("==========列表==========")
def listChanged(a): # 列表:同一引用
    a[0] = 2
    print(id(a))

a = [1]
print("调用函数前:" + str(a))
listChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========集合==========")
def setChanged(a): # 集合:同一引用
    a.add(2)
    print(id(a))

a = {1}
print("调用函数前:" + str(a))
setChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========字典==========")
def dictChanged(a): # 字典:同一引用
    a[1] = "2"
    print(id(a))

a = {1:"1"}
print("调用函数前:" + str(a))
dictChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========数值==========")
def numberChanged(a): # 数值:结果变成不同引用
    print("调用函数时:", id(a))
    a += 1
    print("重新赋值:", id(a))

a = 1
print("调用函数前:" + str(a))
numberChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========字符串==========")
def stringChanged(a): # 字符串:结果变成不同引用
    print("调用函数时:", id(a))
    a += "a[:]" # 假装拷贝
    print("重新赋值:", id(a))

a = "1"
print("调用函数前:" + str(a))
stringChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========元组==========")
def tupleChanged(a): # 元组:同一引用
    print("调用函数时:", id(a))
    a += ("合并两元组",)
    print("重新赋值:", id(a))

a = ("1", "2")
print("调用函数前:" + str(a))
tupleChanged(a)
print(id(a))
print("调用函数后:" + str(a))

print("==========带可变子元素的元组==========")
def tuple2Changed(a): # 带可变子元素的元组:同一引用
    a[1][0] = "22"
    print(id(a))

a = ("1", ["2"])
print("调用函数前:" + str(a))
tuple2Changed(a)
print(id(a))
print("调用函数后:" + str(a))

得到:

==========列表==========
调用函数前:[1]
2268560182080
2268560182080
调用函数后:[2]
==========集合==========  
调用函数前:{1}
2268560447296
2268560447296
调用函数后:{1, 2}        
==========字典==========  
调用函数前:{1: '1'}      
2268560123776
2268560123776
调用函数后:{1: '2'}      
==========数值==========  
调用函数前:1
调用函数时: 2268558420272
重新赋值: 2268558420304
2268558420272
调用函数后:1
==========字符串==========
调用函数前:1
调用函数时: 2268560076912
重新赋值: 2268560559408
2268560076912
调用函数后:1
==========元组==========
调用函数前:('1', '2')
调用函数时: 2268560166464
重新赋值: 2268560558592
2268560166464
调用函数后:('1', '2')
==========带可变子元素的元组==========
调用函数前:('1', ['2'])
2268560559232
2268560559232
调用函数后:('1', ['22'])

总结

  • 作为参数传递进去时,都是传递的内存地址。(所以根据引用计数机制,此时引用数是 +1 的)
  • 但是由于不可变类型无法改变,如果对它进行修改,即都是创建一个新对象,在内存中开辟一个新空间,且在函数内的此次修改并不影响外部的原有变量
  • 可变类型的传递,修改不会新建对象,函数内外一直都是操作同一个对象。
  • 不可变类型的元组内部包含【可变类型的子元素】,它对可变元素的修改仍是遵从可变类型的逻辑的。即修改它的可变子对象,不会重新创建,那么这个元组还是没有发生改变的(指它的内存地址和储存的元素内存地址没有变化,还是那个未变的元组对象,但是内容会被修改)。
  • 不可变数据:Number(数字)、String(字符串)、Tuple(元组);
  • 可变数据:List(列表)、Dictionary(字典)、Set(集合)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值