昨天上午最后一门考完后,这学期的考试周就算是结束了。今天看到身边的同学回家的回家,出游的出游,还有一些在中饭时才起来刷牙洗脸的,不禁感慨自己的生活还是有些太单调了。
今天下午学python时,被值传递和地址传递的问题困扰了很久,在参考了很多有关书籍和资料之后,感觉自己对于python中变量还是有了更进一步的理解。
首先,我的问题来源于在看《Automate the boring stuff with Python》这本书时读到的这样一句话:
“将42(数字)赋给spam变量时,实际上是在计算机中创建值42,并将对它的‘引用’存储在spam变量中。”
一直以来,我所理解的变量传递方式(在C语言框架体系内)分为两种,一种是值传递,即
int x = 1;
这样的形式。这种传递方式只是简单的把变量内容(值)复制到了另一处内存空间(指所创建的变量)中,这样定义的变量我称之为内存变量;另一种是地址传递,即
int list[3] = {0, 1, 2};
int *x = list;
中的指针变量x,这种传递方式则是将对应变量在内存中的地址复制到了新的变量中。C语言用‘ * ’运算符清晰地表明了当前所用的到底是地址本身(%p下显示为一串16位十六进制数),还是这个地址对应内存上所存储的值。理所当然地,我认为python中的变量也会分为这样两种类型,直到我读到了下面引用的第一篇博客。
python是面向对象的语言,所有的变量都是动态类型的,即无需在使用前指定变量类型,这一点与C中的指针(尤其是void型指针)高度相似。指针指向不同的地址,变量所对应的就是不同内容,甚至不同类型的值。因此python中的变量,都可以看作是一个无类型,或者说是任意类型的指针。
我所引用的第二篇博客中有一句话令我印象十分深刻:
“C语言中变量(指内存变量)变的是内存空间中的值,不变的是地址;而在Python中,变量变的是地址,不变的是内存空间中的值。”
在python体系中,每当一个“常量”被创建出来(体现在赋值语句中)时,其在内存空间中的值就一直保持固定了;被它所赋值的变量,实际上享有的是这样一个内存空间所对应的地址。每当为变量赋予新的值时,该变量上原有的地址即被新的“常量”对应的地址所覆盖,原来的那个常量,也会被“自动垃圾收集器”所清理。在每个“常量”的生存期内,其在内存空间上的地址固定不变,只是变量指向不同“常量”时,所对应的地址变了。因而说是“变量的地址在变化,不变的是内存空间中的值”。
用比较形象化的语言来形容,C语言中的内存变量的值,是轮流租用同一间旅舍的不同旅客,而python中的变量所对应的,则是不同的住址。每一处住址里的人们,从出生到死亡,一直都在这或宽敞或狭小的一方天地,静待与外部世界的交流。
python中虽然没有定义正式的常量类型,但是其将数据类型划分为了可变和不可变两类。包含数值、字符串、元组的不可变数据类型,其实便如同C语言中的常量一般,不能对其进行修改操作。当所定义的变量直接指向这样的类型时,想要修改其值,只能通过对变量整体重新赋值来实现。
str1 = 'asdfghjkl'
str1[1] = 'a'
#报错:TypeError: 'str' object does not support item assignment
str1 = 'zxcvbnm'
#此时可对str1进行正确修改
而可变数据类型,如列表、字典等,则可以看作许多不可变数据类型的叠加。对于其中的某个元素的修改,其实对应的是对于指向不可变数据类型变量的重新赋值。
写到这里,文教教室外面的灯已经全黑了。今天就先到这里吧,之后再进行修改与调整。
参考资料:
python学习手册