动态类型

变量,对象和引用python

变量在赋值的时候建立,它能够引用任何类型的对象,而且必须在引用以前赋值。缓存

a = 3

全部赋值操做有三个步骤:函数

  1. 建立一个对象来表明值3
  2. 建立一个变量a,若是它尚未建立
  3. 将变量与新的对象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
相关文章
相关标签/搜索