Python学习之变量、对象和引用
问题的引出
当在Python中运行赋值语句a=3
时,熟悉C语言的朋友肯定会感到奇怪:难道变量a不需要定义吗?Python是怎么知道变量a的类型的?
变量创建
一个变量(也就是变量名),就像a,当代码第一次给它赋值的时候就创建了它。之后的赋值会改变已创建的变量名的值。其实,说得更严格一点,这叫“名称绑定”。
名称用于指代对象(你可以理解为名称是一个指向对象的指针)。名称是通过名称绑定操作来引入的。以下构造会绑定名称:传给函数的正式形参,import语句,类定义,函数定义,以标识符为目标的赋值,for循环的开头等等等等。
对于初学者,只要记住 以标识符为目标的赋值会绑定名称 就可以了。
变量类型
变量永远不会有任何的和它关联的类型信息或约束。类型的概念是存在于对象中而不是变量名中。变量是通用的,它只是在一个特定的时间点,简单地引用了一个特定的对象而已。
变量使用
当变量出现在表达式中时,它会马上被当前引用的对象所代替,无论这个对象是什么类型。此外,所有的变量必须在其使用前明确地赋值,使用未赋值的变量会产生错误。
动态类型
如果清楚地将变量名和对象划分开来,动态类型是很容易理解的。例如:
>>> a = 3
对于上面的赋值操作,Python会执行三个不同的步骤去完成这个请求:
- 创建一个对象来代表值3
- 创建一个变量a,如果它还没有被创建的话
- 将变量a与新的对象3相连接(link)
实际的效果如下图:
Names and objects after running the assignment a = 3. Variable a becomes a reference to the object 3. Internally, the variable is really a pointer to the object’s memory space created by running the literal expression 3.
如图所示,变量和对象保存在内存中的不同部分,并通过连接相关联(这个连接在图中表示为一个箭头)。变量总是连接到对象,并且绝不会连接到其他变量上,但是更大的对象可能连接到其他的对象(例如,一个列表对象能够连接到它所包含的对象)。
在Python中从变量到对象的连接称作引用(reference)。也就是说,引用是一种关系,类似于C语言的指针。
要点:
- 变量是一个系统表的元素,拥有指向对象的连接的空间。
- 对象是分配的一块内存,有足够的空间去表示它所代表的值。
- 引用是自动形成的从变量到对象的指针。
类型属于对象,而不是变量
每一个对象都有两个标准的头部信息:一个类型标识符和一个引用计数器。类型标识符用来标识这个对象的类型,引用计数器用来决定是否可以回收这个对象。
对象的垃圾收集
在Python中,每当一个变量名被赋值给了一个新对象,之前那个对象占用的空间就会被回收(如果它没有被其他的变量名或对象所引用的话)。这种自动回收对象空间的技术叫垃圾收集。
在下面的例子中,每个语句都把变量名x赋值为不同的对象:
>>> x = 42
>>> x = 'hello'
>>> x = 3.14159
>>> x = [1,2,3]
首先注意x每次被设置为不同的对象。再者,尽管这不是真正的情况,效果却是x的类型每次都在改变。
第二,每一次x被赋值给一个新的对象,Python都回收了旧对象的空间。例如,当执行x = 'hello'
时,对象42马上被回收(假设它没有被其他的变量名或者对象所引用)。
在内部,Python是这样来实现这一功能的:它在每个对象中保持了一个计数器,计数器记录了当前指向该对象的引用的数目。一旦(并精确在同一时间)这个计数器被设置为0,这个对象的内存空间就会被自动回收。在前面的介绍中,假设每次x都被赋值给一个新的对象,而前面的一个对象的引用计数器变为0,就会导致它的的空间被回收。
垃圾收集最直接的好处就是可以在代码中任意使用对象而不需要考虑释放内存空间。与C语言这样的底层语言相比,真是给程序员省了不少麻烦。
【End】
参考资料
《Python学习手册(第4版)》,机械工业出版社