首先要明确的是:Python参数传递采用的 都是按引用传递。
那么,有人就会有 疑惑:为什么数字,字符串,元组的等看起开好像是类似于C语言的按值传递, 而list,dict又像是C++的引用传递呢?

我认为,这是因为:python中有可变对象和不可变对象之分。

对可变对象都来说,就好象是按引用传递,对不可变对象来说,就好象是按值传递。我们还是来弄清到底为什么是这个现象。



#!/usr/bin/env python3
#-*-coding:utf-8-*-

x = 5

def test(x):
    print('函数里的x变量的最初地址是:',id(x))
    x+=1
    print("加1操作后,函数里的x变量的值是:", x)
    print('加1操作后,函数里变量x的地址是:',id(x))



if __name__=='__main__':
    print('最开始x的地址是:',id(x))
    test(x)
    print('最后,函数外x变量的值是:',x)



运行结果:

>>>
最开始x的地址是:                          1619120656
函数里的x变量的最初地址是:        1619120656
加1操作后,函数里的x变量的值是: 6
加1操作后,函数里变量x的地址是: 1619120672
最后,函数外x变量的值是:             5

我们发现,最开始x的地址  和   原来地址为1619120656的整数5在原地变为6,而是另外临时创建一个整型对象6,再让函数里的 x去引用?这就是因为:int 类 对象是不可变对象。


也即是说:在地址为:1619120656的这个数据不可更改,只读不可写。

画个图

def python 传值 python按值传递_引用传递

当函数调用完毕,局部变量就会被销毁,相当于del x ,内存对象 6 没有被任何变量引用,就会被垃圾回收。也就是在内存上被清理。全局变量x最终还是引用对象5,没有任何改变。python之所以这样设计,我想是考虑到代码的安全和管理。因为数字,字符串等类型是最常用的,如果代码里有n处同时引用了一个数字,其中有1处操作将此数字改变了,n-1处也不会改变,这确实是一件好事。


那么对于可变对象,大家应引申一下就明白了。由于是可变对象,只要在某一处通过某个操作被改变,那n-1处也就会随之更新。




最后,看看ython的内存管理:

Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被引用了多少次。每当引用一次Python对象,相应的引用计数就增1,每当消毁一次Python对象,则相应的引用就减1,只有当引用计数为零时,才真正从内存中删除Python对象,也就是垃圾回收。


还要说明的一点是:既然python中,一切皆对象,那么,在使用数据对象时,除了字面值外,一切皆引用。

因为python的变量本身不含数据,那么,在使用对象时,就只能靠变量去引用对象。然后再操作变量,达到操作数据对象的目的。