Python-动态性区分变量和对象

理解 Python 的动态类型机制,需要首先明白 Python 中变量和对象的关系。

Python 的对象是存储在内存当中,占有相当空间大小,具有具体类型的一种数据结构。即 Python 对象对应内存中的一段地址空间。

然而,Python 的变量只是一个名字,它可以指向任意一段内存地址,即任意类型的对象。也就是说 Python 的变量只是 Python 对象的引用,并没有具体的数据类型。

Python 对象的创建

Python 对象是由赋值语句右侧的表达式计算的结果创建。上面赋值语句的操作流程:

计算表达式的值为 6

在当前作用域中创建一个值为 6 的整型对象,并存储在内存当中

把这个整型对象的内存地址传给变量 a,即:变量 a 引用这个整型对象

同样下个赋值语句:内存中创建一个列表类型的对象

变量 a 舍弃整型对象,指向 [1, 2, 3] 的列表对象

变量的使用是为了便于对对象的调用,变量会在程序进入内存之前,被相应的对象替换

变量 a 舍弃的整型对象 6,会被 Python 中的垃圾回收机制自动回收被舍弃的对象

多个变量引用同一个对象

由于不同的对象拥有不同的特性,当多个变量引用同一个对象时,会出现些许的不同。可将对象大体分为两部分:不可变类型的对象和可变类型的对象。

1. 不可变对象的引用

不可变对象有:整型、浮点型、字符串、元祖。 这些类型的对象所占用的内存不会被修改,直至对象被回收。当变量引用不可变对象,想改变对象的值时,只会重新创建对象,并把变量指向新对象。

执行结果:

开始 a 和 b 变量都指向 “hello” 对象,可以通过 方法获取对象的存储地址来判断 a 和 b 是否指向同一个地址,当修改 a 引用对象的值,a 指向的地址就会发生改变。

2. 可变对象的引用

可变对象有:列表,集合,字典以及 class 关键字自定义的对象。这些类型的对象所占用的内存是可以被修改的。但是变量指向的内存地址不会改变。

执行结果:

开始 a 和 b 变量都指向 [1, 2, 3]列表,当修改列表中元素的值时,a 指向的地址没有发生改变。

3. 对象的复用机制

对象的复用机制是在 Python 中为对象提供了一个对象缓存池,当在缓存中能找到对象的时候,说明此对象已经被创建过,Pythont 就不会再重新创建,会让变量引用已经存在的对象(这些对象都是不可变对象),减轻系统压力,增加系统性能。

可复用的不可变对象:整型、浮点型、字符串。

注:不可变对象元祖不可复用

执行结果:

同时创建 a、b相等的两个字符串对象,x、y相等的两个列表对象,a 和 b 的引用的地址相同,说明 a 和 b 引用的是同一个对象;x 和 y 引用对象的地址不同,说明 [1, 2, 3] 对象被创建了两次,x 和 y 引用的是不同的对象。

对象的删除

Python 对象由三部分组成:类型,引用计数器,数据结构。引用技术器统计有多少个变量引用了此对象。一旦这个计数器被设置为零,这个对象的内存空间就会自动回收。写程序时不需要过多的考虑内存的释放,内存的管理由 Python 垃圾回收机制自动处理。

对象的拷贝

有的时候,不希望多个变量同时引用同一个对象,但是又希望它们引用的对象相等,避免在以后的对象操作时,它们同事修改同一个对象,造成混乱。这时就用到对象的拷贝。主要针对的是可变对象的操作。

1. 浅拷贝

浅拷贝仅将对象的本身进行复制,而对象内部引用的其他对象不复制。

执行结果:

y 由 x 赋值得到,y 与 x 同时引用同一个对象,所以地址相同,子对象 x_sub 地址也相同。z 由 x 复制得到,z 引用新创建的对象,z 与 x 引用不同的对象,但由于是浅复制,z 与 x 中的子对象没有复制,属于同一个子对象。

2. 深拷贝

深拷贝不止将对象本身进行复制,对象内部引用的其他对象也进行复制。

import copy

执行结果:

可以看到 z 和 x 不仅本身对象内存地址不同,子对象 x_sub 内存地址也不同。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181022G1ZFWB00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励