变量、对象、引用

变量

1
a = 1

这里a叫做变量;1是对象;一个变量指向一个对象叫做这个对象产生了一个引用,和Java类似

  • 变量类型:一个变量不会有任何类型信息或者约束,类型的概念和对象关联,而不是变量名字
  • 变量的使用:当变量出现在表达式中,他会立即使用当前指向的对象替换,这导致变量在使用之前都必须要被显示的赋值,使用未被赋值的变量时会产生错误
  • 变量和对象:变量和对象是存储到不同的内存中,变量永远会指向对象不会指向其他变量,对象是有可能指向别的对象的(list)

对象

  • 每个对象都有两个标准的 header fields:type designator标识对象的类型,reference counter记录引用次数
  • 对象创建时会分配一片内存空间用来存储类中的数据,作为优化有一部分的数据(较小的integers和strings)是用缓存池来存储的,不用每次都在对象内存中去单独存储

对象回收

1
2
a = 3
a = 4

这个时候对象3会被回收,Python主要通过引用计算法来进行垃圾回收

共享引用

  • 对不可变的类型
1
2
3
4
a = 3
b = a # b会创建指向对象3的引用
a = 4 # 不会影响b指向对象3
a = a + 1 # 对象5会作为加号的结果放到新的内存空间,integer是不可变类型,所以会分配新的内存空间,并为a创建指向对象5的引用
  • 对可变的类型
1
2
3
a = [1,2,3]
b = a # b也指向数组对象
a[0] = 2 # 这时是数组对象发生了变化,不是a引用了新的对象,a和b还是指向同一个对象,当然b[0]也发生了变化

判断相等

1
2
a == b  # 对值的判断
a is b # 对指向的对象的判断,更严格的判断

整数对象

  • integer是一个不可变类型,这就是说一个integer对象的内存中的数据是不会改变的,任何的运算都只会去新建对象来存放运算后的数据

  • 对于整数对象,有一个缓存池,这个缓存池的大小是[-5,256],这个很好证明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
a = -5
b = -5
hex(id(a)) # '0x109d7ffc0'
hex(id(b)) # '0x109d7ffc0'

a = -5
b = -5
hex(id(a)) # '0x10a027fd0'
hex(id(b)) # '0x10a027f70'

a = 256
b = 256
hex(id(a)) # '0x109d82060'
hex(id(b)) # '0x109d82060'

a = 257
b = 257
hex(id(a)) # '0x10a027fd0'
hex(id(b)) # '0x10a027f50'

这块区域被称为小整型缓存池,静态分配,在Python初始化时被创建,用的时候直接去取就行,不用创建,超出这个范围的就是用到的时候创建的并且不会复用,也就是说创建两个257在内存中就有两片不同的空间用来存储了这两个字面量,再将两个变量分别指向这两片空间地址

string

list和dict