变量,对象和引用python
变量在赋值的时候建立,它能够引用任何类型的对象,而且必须在引用以前赋值。缓存
a = 3
全部赋值操做有三个步骤:函数
在运行a=3后,变量a变成对象3的一个引用,在内部,变量其实是到对象内存空间的一个指针。spa
类型属于对象,而不是变量指针
a = 3 a = 'spam' a = 1.23
变量名没有类型,咱们只是把a修改成不一样的对象的引用。所以,没有改变a的类型,而是让变量引用了不一样类型的对象。code
每一个对象都包含了一个头部信息,其中标记了这个对象的类型。对象
对象的垃圾回收blog
每当一个变量名被赋予了一个新的对象,以前那个对象占用的空间就会被回收。这种技术叫作垃圾回收。内存
x = 42 x = 'shrubbery' x = 3.1415 x = [1, 2, 3]
在内部,python在对象中保持了一个计数器,计数器记录了当前指向该对象的引用的数目。一旦这个计数器被设置为零,这个对象的内存空间就会自动回收。字符串
共享引用
a = 3
b = a
a和b引用了相同的对象,指向了相同的内存空间。多个变量引用同一个对象,这叫共享引用。
a = 3 b = a a = 'spam'
这时候,b仍然引用原来的对象3。
a = 3 b = a a = a + 2
a会赋值为一个彻底不一样的对象,而不会影响到b。b仍是3对象。
共享引用和在原处修改
对于支持在远处修改的对象,共享引用时须要当心,由于对一个变量名的修改会影响其余变量。
L1 = [2, 3, 4] L2 = L1
L1[0] = 24
L1
#[24, 3, 4]
L2
#[24, 3, 4]
列表对象内的元素的远处修改会印象程序其余部分。若是不想要这样的现象发生,须要python拷贝对象,而不是建立引用。拷贝列表能够用内置列表函数,或者标准库copy模块,或者从头至尾的分片。
L1 = [2, 3, 4] L2 = L1[:] L1[0] = 24 L1 #[24, 3, 4] L2 #[2, 3, 4]
共享引用和相等
x = 42 x = 'shrubbery'
由于python会缓存而且复用小的整数和小的字符串,这里的对象42也许并不会回收,它可能会保存在一个系统表中,等待下一次代码生成一个42来重复利用。
python中有两种办法检查是否相等。看共享引用的例子:
L = [1, 2, 3] M = L L == M #True L is M #True
==操做符检查值是否相等,is操做符,检查对象的同一性,若是两个变量指向同一个对象,那么会返回True。
实际上,is比较实现引用的指针,因此这是一种检查共享引用的方法。若是变量名的引用值相等,可是是不一样的对象,它的返回值会是False。
L = [1, 2, 3] M = [1, 2, 3] L == M #True L is M #False
但当咱们对小的数字作一样的操做:
x = 42 y = 42 x == y #True x is y #True
由于小的数字和字符串被缓存复用了,因此is告诉咱们它们引用的使用一个对象。
你能够向python查询一个对象引用的次数:在sys模块中的getrefcount函数会返回对象的引用次数。例如,在IDLE GUI中查询整数对象1时,会返回有837次引用。
import sys sys.getrefcount(1) #837