Python中处理变量的方式和其他语言有很大的不同,尽管这些区别看上去没有那么明显。
Python中所有东西都是对象,变量只是指向对象的指针。所以类型是跟着对象走的,而不是跟着变量走。比如下面的代码在Python中是完全正确的(尽管实际上很少有人这么写代码):
a = 300
a = ‘spam’
a = 1.23
第一行,Python新建了一个整数对象,值为300,同时变量a指向这一对象。第二行,Python新建一个字符串对象’spam’,并且让变量a指向这一变量,并且,由于没有其他变量指向300这一对象,这一对象所占用的内容会被Python自动回收。第三行发生的事情是类似的。
好象也没什么,很多解释型的语言,似乎都是这样。下面再来看点不一样的东西。比较一下以下两段代码中的最后一行会返回什么:
代码1:
a = 300
b = 300
a is b
代码2:
a = 300
b = a
a is b
对于代码1,a is b返回False,也就是说,a和b指向了不同的对象,只是他们的值都300。对于代码2,a is b将返回True,a和b指向了同一个对象。如何说明他们确实是同一个对象呢?来看:
a = [1, 2, 3]
b = a
a.append(4)
这时,a等于[1,2,3,4],b也等于[1,2,3,4],因为他们指向的是同一个对象。再来看:
代码3:
a = 300
b = 300
a = a + 100
代码4:
a = 300
b = a
a = a + 100
问,执行完上面两段代码后,a、b各是多少?
毫无疑问,无论代码3还是4,执行后,a都应该是400,关键是b。对于代码3,由于已经知道a,b原来指向的就是不同的对象,因此,b应该还是300。对于代码4,或许有人认为b应该400,因为“a is b”是True,而且刚才也看到了list的例子。其实b还是等于300。
这里涉及到Python数据类型的另一个性质。Python中,整数对象是immutable的,也就是不可变的,一旦生成,其值是不可更改的。a = a + 100这一句的实际执行过程是,取出a当前指向对象的值300,加上100后为400,则新建一个值为400的整数对象,并令a指向该对象。也就是说,无论代码3还是代码4,a都不是原来的a了,只是在代码3中,这一点表现的并不明显。而在代码4中,由于b仍指向原来的300那个对象,因此,300不会被收回(每个对象有个计数器,自动记录有多少变量指向该对象,只有当计数器减为0时,Python才会自动回收该对象),b的值也不会改变。而刚才list的例子中,由于list是可变类型的,因此改变a,就是改变b。
Python越学越有趣了。