Python将数据放在对象中,变量只不过是对象的一个引用;变量为内存中某个点取了一个名字而已。所有对象都有一个唯一的身份号、类型以及值。
1. Object identity
因为是对象,而不是变量,有一个数据类型,所以一个变量在某个时候可以引用一个list,而在另一个时候可以引用一个浮点数。一个对象它的类型永远无法改变,但对于lists以及其他一些mutable类型,它们的值是可以改变的。
Python提供了 id(obj) 这样一个函数,它返回的就是对象的identity,也就是对象在内存中的地址。
>>> shoppingList = [‘candy’,’cookies’,’ice cream’]
>>> id(shoppingList)
17611492
>>> id(5)
3114676
操作符 is 作用是比较两个对象的identity,判断它们是否是同一个对象。
>>> junkFood = shoppingList # Both reference the same object
>>> junkFood is shoppingList
1
>>> yummyStuff = [‘candy’,’cookies’,’ice cream’]
>>> junkFood is not yummyStuff # Different identity, but...
1
>>> junkFood == yummyStuff # ...same value
1
因为变量仅仅是引用某个对象,修改了某个mutable对象的值后,所有引用该对象的变量都可以看到该变化:
>>> a = [1,2,3,4]
>>> b = a
>>> a[2] = 5
>>> b
[1, 2, 5, 4]
>>> a = 6
>>> b = a # Reference the same object for now.
>>> b
6
>>> a = a + 1 # Python creates a new object to hold (a+1)
>>> b # so b still references the original object.
6
2. Counting references
每个对象都有一个引用计数,指明有多少变量在引用该对象。当你将一个变量附到一个对象上,或者当把一个对象放到一个list或其他容器中时,引用计数就会增加。当销毁、reassign、或从容器中移除一个对象,引用计数就会减少。当引用计数到达 0,Python的垃圾收集器就会销毁该对象,重新开垦这块被使用的内存。
sys.getrefcount(obj) 函数返回指定对象的引用计数。
====新特性
从2.0版开始,Python现在还收集只带循环引用的对象。例如,
a = []; b = []
a.append(b); b.append(a)
a = 5; b = 10 # Reassign both variables to different objects.
The two list objects still have a reference count of 1 because each is a member of
the other’s list. Python now recognizes such cases and reclaims the memory used
by the list objects.
========================================================================================
要记住,del语句删除的是变量,而不是对象,尽管如果一个你要删除的变量是一个对象的唯一引用,随后Python也会删除该对象。
>>> a = [1,2,3]
>>> b = a # List object has 2 references now
>>> del a # Back to 1 reference
>>> b
[1, 2, 3]
你也可以创建 weak references,或者那些不会影响一个对象的引用计数的引用。