1.不需要声明---变量与对象的关系
python的动态语言特点决定所有变量都是动态监测的。这是python的动态类型模型。
变量如果没有被赋值,不能直接使用。
>>>a # wrong
>>>a = 4 #right
>>>a
4
那么a = 4 这个语句python做了什么呢?
1.1 创建一个与4关联的object。(python中一切都是object)
1.2 如果a不存在,创建变量a。
1.3 将a 连接到object 3 上(创建a对object的引用)。
pathon将变量存放到一个表里。将object放在动态存储区中。用指针关联它们。
为了提高效率。如果有多个变量的值一样(限值类型),python会在变量表中创建不同的变量,但只会创建一份object.让这些变量指向它。所以,相应地,object中会有一个引用计数区域来记住有多少个变量指向了它。当然,object中还有一个 type designator来表示object的类型,所以类型永远只于对象关联。而变量,实质上就是一个指针,到处指指罢了:
>>>a = 3 # a 我代表3啦
>>>a = 'spam' #a 我指向‘spam’啦。3没有被任何变量指,看来有被系统回收的危险了
这边注意与c语言的本质区别。c中变量是有类别的,就算指针也是。而python中,变量没有类别。
我们还注意到现在3没有被任何变量值向,3这个object里的引用计数变成了0。会被当作垃圾回收的。我们就不用管了。
>>>a = 3
>>>b = 3
>>>a = 3
>>>b = a
现在再看上面代码。前者和后者含义是相同的。因为我们知道变量什么都不是,所以任何变量最终都会指向一个object的:
但是,这样好是好,如果b改变了,a不就委屈了。(我好心和你分享,你却背着我干坏事:)
对于这种情况,为了使大家都公平,python决定如果有一个变量想改变object的值。让这个变量指向新的object。而不动原来object。(除非这个object只属于你,是同类型)
当然,这并不是对于任何object都成立的。对于list这种有结构,有气势的object,或是真正被类实例化的object。修改一点东西和属性无上大雅的。但此时你就要小心了:
>>>L1 = [2, 3, 4]
>>>L2 = L1
>>>L1[0] = 0
>>>L1
[0, 3, 4]
>>>L2
[0, 3, 4]
从上面可以看出python只在原对象上做了修改。dictionary 与 set 也类似。
2.完完全全地copy
类似于java,可以使用copy来完全复制object:
>>>import copy
>>>x = copy.copy(y) #第一层完全拷贝
>>>x = copy.deepcopy(Y) #所有层完全拷贝
好好体会下面的代码:
第一层拷贝,可以使第一层完完全全copy出去。a1[0]改变后,a2[0]并没有改变,但第二层的2还是改变了。
>>> a1 = [1, [2, 3], 4]
>>> a2 = copy.copy(a1)
>>> a1[0] = 0
>>> a2
[1, [2, 3], 4]
>>> a1[1][0] = 0
>>> a2
[1, [0, 3], 4]
深层拷贝,第n层也拷贝了。
>>> a1 = [1, [2, 3], 4]
>>> a2 = copy.deepcopy(a1)
>>> a1[0] = 0
>>> a2
[1, [2, 3], 4]
>>> a1[1][0] = 0
>>> a2
[1, [2, 3], 4] #注意还是2!没受影响
>>>
3.引用相等还是内容相等?
类似于java, 判断变量引用相等,用is, 内容相等用 ==
内容相等,不一定是同一个对象
>>> l = [1, 2, 3]
>>> r = [1, 2, 3]
>>> l == r
True
>>> l is r
False
引用同一个对象
>>> l = [1, 2, 3]
>>> r = l
>>> l == r
True
>>> l is r
True
4.查看引用计数
比如我要查看9988这个object的引用计数
>>>import sys
>>>sys.getrefcount(9988)
end