python中参数的传递

python中可变对象进行引用传递,不可变对象进行值传递
因为python中的变量其实都是指针,例如:
对于不可变对象来说:

a=1
b=1
#id(a)==id(b)
a=2
b=1
#id(a)!=id(b)
a=2
b=2
#id(a)==id(b)

内存中1或者2其实只占用了一个地址,不管多少对象引用它,都只有一个地址,都只占用了一块内存,数值的修改实际上是让变量指向了一个新的对象。
不可变可以理解为x引用的地址处的值是不能被改变的,重新赋值不可变变量实际是使其重新指向另一块内存,而不是改变原内存处存放的值。

对于可变对象来说
例如列表、集和、字典是引用类型,本身可以进行修改。

a = [1,2,3]
b = a #此处进行了引用传递
#id(a)==id(b)
b = [1,2,3]
#id(a)!=id(b)
a_last = a
a.append(4) #值的变化不会引起地址变化
#a=[1,2,3,4] a_last=[1,2,3,4]
#id(a) == id(a_last) 
#id(a)==140047576300360
a = [1,2]
#id(a) == 140047576327240
#对可变对象进行重新赋值会改变对象的地址

因此可变数据的操作不能是进行直接的赋值,只能是类似与append之类的操作。
并非所有的不可变对象都是不可变的。

如前所述,Python容器比如元组,是不可变的。这意味着一个tuple的值在创建后无法更改。但是元组的“值”实际上是一系列名称,它们与对象的绑定是不可改变的。关键点是要注意绑定是不可改变的,而不是它们绑定的对象。
引用源自:

让我们考虑一个元组t =(‘holberton’,[1,2,3])
上面的元组t包含不同数据类型的元素,第一个元素是一个不可变的字符串,第二个元素是一个可变列表。元组本身不可变。即它没有任何改变其内容的方法。同样,字符串是不可变的,因为字符串没有任何可变方法。但是列表对象确实有可变方法,所以可以改变它。这是一个微妙的点,但是非常重要:不可变对象的“值” 不能改变,但它的组成对象是能做到改变的。
其实主要原因是元组内保存的是变量(也就是内存地址)。所以当变量指向对象发生变化时,如果导致变量发生变化(即不可变类型),此时元组保证该不可变类型不能修改。而如果当变量指向对象发生变化时,如果不会导致变量发生变化(即可变类型),此时元组中存储的该可变类型可以修改(因为变量本身并无变化)。

即是:

t=('hello',[1,2,3])
t[1].append(4)
# t=('hello',[1,2,3,4])

总结:

python中的不可变数据类型,不允许变量的值发生变化,如果改变了变量的值,相当于是新建了一个对象,而对于相同的值的对象,在内存中则只有一个对象,内部会有一个引用计数来记录有多少个变量引用这个对象;

可变数据类型,允许变量的值发生变化,即如果对变量进行append、+=等这种操作后,只是改变了变量的值,而不会新建一个对象,变量引用的对象的地址也不会变化,不过对于相同的值的不同对象,在内存中则会存在不同的对象,即每个对象都有自己的地址,相当于内存中对于同值的对象保存了多份,这里不存在引用计数,是实实在在的对象。

所以Python中的参数传递都是传递引用,也就是传递的是内存地址。只不过对于不可变类型,传递引用和传递值没什么区别。而对于可变类型,传递引用是真的传递内存的地址。
听说python只允许引用传递是为方便内存管理,因为python使用的内存回收机制是计数器回收,就是每块内存上有一个计数器,表示当前有多少个对象指向该内存。每当一个变量不再使用时,就让该计数器-1,有新对象指向该内存时就让计数器+1,当计时器为0时,就可以收回这块内存了。当然还有其他的GC方法,否则计数器回收,无法解决循环引用的问题。

值传递: 表示直接传递变量的值,把传递过来的变量的值复制到形参中,这样在函数内部的操作不会影响到外部的变量。

引用传递: 把引用理解为变量(标识符)与数据之间的引用关系,标识符通过引用指向某块内存地址。而引用传递,传递过来的就是这个关系,当你修改内容的时候,就是修改这个标识符所指向的内存地址中的内容,因为外部也是指向这个内存中的内容的,所以,在函数内部修改就会影响函数外部的内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值