python函数是值传递还是引用传递

在网上看python的基础知识,看到函数这一章的时候,看到这么一段话:

       所有参数(自变量)在Python里都是按引用传递。如果你在函数里修改了参数,那么在调用这个函数的函数里,原始的参数也被改变了。

def changeme( mylist ):
   "修改传入的列表"
   mylist.append([1,2,3,4]);
   print "函数内取值: ", mylist
   return
 
list1 = [10,20,30];
changeme( list1 );
print "函数外取值: ",list1

 运行结果:

函数内取值:  [10, 20, 30, [1, 2, 3, 4]]
函数外取值:  [10, 20, 30, [1, 2, 3, 4]]
[Finished in 0.2s]

感觉好像真的是引用传递,于是乎自己写了点代码验证:

def changeA(a):
    a = 10

num = 2
changeA(num)
print num

打印出的结果却是 “2”。。。。蒙圈了!。。。说好的引用传递呢。

网上搜索了一番,发现很多人是这么说的:

    不可变类型引用传递,可变类型值传递。

原来是这样,但啥是可变类型不可变类型,又在网上搜索了一下:

    在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象

这样好像可以解释上面的代码了,但是个人觉得传对象引用(对象传递)更好理解

在python中,变量就是一个变量,没有类型可言,我们可以给一个变量赋各种类型的值

a=2
a="test"
a=[2,3,3]

而类型是属于对象,一个类型具体的值在内存中都一个地址,改变变量的值其实是改变了它引用的地址

print id(1)
print id(2)
a=1
print id(a)
a=2
c=2
print id(a)
print id(c)

运行结果:

23044824
23044812
23044824
23044812
23044812
[Finished in 0.1s]

  

上面代码可以看出,整型1,2在内存中有自己的地址,把他们赋值给变量的时候,就是把自己的地址引用给了变量。

现在来解释上面的代码:

    列表[10,20,30]是一个对象,有自己的内存地址,比如是:123456,变量list1用这个地址指向了这个列表。调用函数changeme的时候,这个列表对象的地址传给了mylist,此时list1和mylist都指向了同一个列表

。mylist调用append方法,因为列表是可变类型(个人理解为可以改变值,但地址不变),地址123456的列表变为[10, 20, 30, [1, 2, 3, 4]],  所以list1的值也是[10, 20, 30, [1, 2, 3, 4]]。

     第二段代码,num=2, 2也是一个对象,假如2在内存的地址是:54321,此时变量num的地址是:54321。调用函数changeA,此时变量a的地址也是54321,此时a=2,接着a=10,因为数字类型是不可变类型,2不能直接变为10,10在内存中是另外一个地址,比如54330。上面说过改变变量的值其实是改变引用的地址,因此当a=10执行完后,变量a的地址是54300,而num的地址依然是54321,其值也就是2

再附上个链接参考一下:

http://www.cnblogs.com/bovine/archive/2011/11/26/2264390.html

猜你喜欢

转载自muchfly.iteye.com/blog/2310536