Python与C
在C中,我们明确的知道,如果加上引用符号 &, 就代表希望传递一个变量的引用。在函数中对这个变量做出的任何变化都会真实的改变这个变量本身的值。(实际上是通过指针操作)
而Python相比于C,由于不再引入指针的概念,因此就没有非常明确的区分,告诉我们这个行为传递的是一个引用还是拷贝。
尽管Python一切皆是对象,但是有些情况下,还是要清楚,函数的行为是否会改变对象的状态
如何区分?
Python中,单个变量都是const的。一个string是const的,一个int是const的……
所以对于单个变量——你在使用它的时候,希望更改它的值,那么一定记得用:a = a + 1
最主要的问题在list类型。(其他容器同理),下面三个程序能够作为很好的说明:
【1】传递list,并对list本身的名字来操作(预测结果,list中的成员应该改变)
def list_ret_refer(lis):
for i in lis:
lis[lis.index(i)] = -1
return lis
lis = [1,2,3,4,5]
ret = list_ret_refer(lis)
print lis
print ret
输出结果:
[ -1 , -1 , -1 , -1 , -1 ]
[ -1 , -1 , -1 , -1 , -1 ]
结论:
对于list,和C中数组一样,是能够在函数中改变内容的。
list容器应该仍然是基于指针的原理
【2】 函数中,复制一份copy,操作copy(预测结果是copy改变,lis不变)
def list_ret_copy1(lis):
copy = lis
for i in copy:
copy[copy.index(i)] = -1
return copy
lis = [1,2,3,4,5]
ret = list_ret_copy1(lis)
print lis
print ret
输出结果:
[ -1 , -1 , -1 , -1 , -1 ]
[ -1 , -1 , -1 , -1 , -1 ]
看,这个就值得思考了。
用C的知识解释,竟然copy本身获得的值是lis的地址!
因此可知,python中的list容器实际上是一个地址,指向一片内存存放内容。而赋值行为则只赋地址。
仔细一想也是合理的,从string不可变化就可以看出一些迹象
【3】该如何传递一份list的复制?
def list_ret_copy2(lis):
copy = lis[:]
for i in copy:
copy[copy.index(i)] = -1
return copy
lis = [1,2,3,4,5]
ret = list_ret_copy2(lis)
print lis
print ret
输出结果:
[ 1 , 2 , 3 , 4 , 5 , ]
[ -1 , -1 , -1 , -1 , -1 ]
copy = list [ : ] ,实现了copy复制list!
可见。python中的list对象在执行 [ a:b ] 操作的时候,新开辟了一段区域给copy!
结论
虽然Python中不强调指针,但实际上,不是Python锉,而是:Python已经智能到能够给你自动使用指针了啊!!!
反正我是再也不会去想 return 一个东西,会不会复制太多份降低效率 这样的白痴问题了。。。
一切皆对象,一切皆指针
【完】