Python的Dynamic typing有些类似于C语言的指针,在C中,一个变量可以指向任何地址空间,在Python中,一个变量也可以指向任何type的数据对象。变量的指向可以在程序运行过程中变化,这就是我理解的Dynamic typing。
Python是高层次的编程语言,在使用Python的时候,我们要忘掉用C开发时的习惯,不要关注底层细节。不需要关心这个变量占几个字节,不需要考虑这个指针free之后,有没有赋空值,不需要考虑溢出等等。
在Python中,所有的一切都是对象,包括一个小小的变量。先看下面的代码示例:
>>> aa = 1
>>> id(aa)
1469710800
>>> aa = 2
>>> id(aa)
1469710832
id这个builtin函数返回的是变量所指向的地址,当然,这个地址我们看不懂,不过至少我们可以看到,在给aa重新赋值之后,地址变了!
这里就是理解Python Dynamic typing的关键:
给aa重新赋值,不是改变aa的值,而是让aa指向另外一个地址,这个地址含有一个新的值!
Python中变量是类似于C语言的指针的存在
我们还可以这样:
>>>
>>> aa = 1
>>> id(aa)
1469710800
>>> aa = 2
>>> id(aa)
1469710832
>>>
>>> aa = '333'
>>> id(aa)
10637360
让aa指向一个string对象。
再看两个图:
共享引用
改变的值指向,而不是对象值
Python的垃圾回收
Python是使用引用计数方式来进行垃圾收集。
例如上例中当aa重新被赋值'333'时候,由于对象1和2的引用计数从1到0(给aa赋值'333'时候'333'的引用计数加1),所以自动进行了垃圾回收.
但是有个问题是:如果在Python中发生,两个对象互相引用,那么引用计数的方式是否会失效?还是Python本身也可以使用"离开作用域则对象失效"的垃圾收集方式。这确实无法避免(互相引用),所以有些Python实现使用了"离开作用域则进行变量销毁"的垃圾收集机制。
可变(mutable)对象和不可变(immutable)对象
元组(tuple)、数值型(number)、字符串(string)均为不可变对象;
而字典型(dictionary),列表型(list),集合(set)的对象是可变对象。(Python官方对mutable对象的解释是:Mutable objects can change their value but keep their id().)
我的理解:对象是不可变的,即变量指向的那块内存空间的内容不能变;对象是可变的,即变量指向的那块内存空间的内容可以改变。而函数调用,传递的都是变量的指向(ref)。
>>> kk = 5
>>>
>>> def test(pp):
... print(id(pp))
...
>>>
>>> id(kk)
1469710928
>>> test(kk)
1469710928
>>>
变量引用的比较
直接看代码吧:
>>> aa = 1
>>> id(aa)
1469710800
>>> aa = 2
>>> id(aa)
1469710832
>>>
>>> aa = '333'
>>> id(aa)
10637360
>>>
>>> bb = aa
>>> bb == aa
True
>>> bb is aa
True
>>>
>>> import sys
>>> sys.getrefcount(1)
106
>>> sys.getrefcount(2)
76
>>> sys.getrefcount('333')
4
>>> sys.getrefcount(aa)
3
>>> sys.getrefcount(bb)
3
>>>
可以直接使用is来进行比较判断。