给妹子讲python-S01E10动态类型与共享引用
微信公众号: python数据科学家
知乎专栏: 《给妹子讲python》
https://zhuanlan.zhihu.com/c_147297848
前文传送门:
给妹子讲python-S01E07字符编码历史观:从ASCII到Unicode
给妹子讲python-S01E08理清python中的字符编码方法
【要点抢先看】
1.python采用了动态类型机制
2.python变量本质上是对内存空间的指针
3.python的垃圾收集机制
4.python的共享引用现象
【妹子说】这段时间以来,我一直有个疑问,C语言中可以看到int a = 1这种表达,可是python中怎么没见到这些?
回答这个问题,就得谈谈python中的对象引用机制和动态类型。
的确,python使用变量的时候都没有声明变量的类型,这一点和C语言不同。但是,变量还可以工作,因为在python中类型是在运行的过程中自动决定的,而不是通过代码声明的,这意味着没有必要事先声明变量。
在python中,我们要明确一个概念:变量名和对象是划分开的,变量名永远没有任何关联的类型信息,类型是和对象关联的,而不存在于变量名中。一个变量名当第一次被赋值的时候被创建,而当新的赋值表达式出现时,他会马上被当前新引用的对象所代替。这就是python所谓的动态类型机制。具体看一个例子:
a = 'abcde'
print(a)
a = [1,2,3,4,5]
print(a)
abcde
[1, 2, 3, 4, 5]
结合上面这个简单的例子,我们再来从头仔细理一理:
1、创建了一个字符串对象’abcde’,然后创建了一个变量a,将变量a和字符串对象 ‘abcde’相连接,
2、之后又创建了一个列表对象[1,2,3,4,5],然后又将他和a相连接。
这种从变量到对象的连接,我们称之为引用,以内存中的指针形式实现。因此直白的说,在内部,变量事实上是到对象内存空间的一个指针,而且指向的对象可以随着程序赋值语句而不断变化。
总结一下:变量名没有类型,只有对象才有类型,变量只是引用了不同类型的对象而已。每一个对象都包含了两个头部信息,一个是类型标志符,标识这个对象的类型,以及一个引用的计数器,用来表示这个对象被多少个变量名所引用,如果此时没有变量引用他,那么就可以回收这个对象。
基于上面谈到的引用机制,我们再说说Python的垃圾收集机制。
还是上面那个例子,每当一个变量名被赋予了一个新的对象,那么之前的那个对象占用的空间就会被回收,前提是如果他没有被其他变量名或者对象引用。这种自动回收对象空间的机制叫做垃圾收集机制。
即当a被赋值给列表对象[1,2,3,4,5]时,字符串对象的内存空间就被自动回收(前提是如果他没有被别的变量引用)
具体的内部机制是这样的:python在每个对象中保存了一个计数器,计数器记录了当前指向该对象的引用的数目。一旦这个计数器被设置为0,这个对象的内存空间就会自动回收。当a被赋值给列表对象后,原来的字符串对象‘abcde’的引用计数器就会变为0,导致他的空间被回收。这就使得我们不必像C++那样需要专门编写释放内存空间的代码了
【妹子说】那再说说共享引用的内容吧:
如下所示,多个变量名引用了同一个对象,称为共享引用:
a = 'abcde'
b = a
print(a)
print(b)
abcde
abcde
此时字符串对象’abcde’的引用计数是2,我们进一步往下看如果我们此时对变量a重新赋值呢?
a = 'abcde'
b = a
a = [1,2,3,4]
print(a)
print(b)
[1, 2, 3, 4]
Abcde
结果是显而易见的,变量a变成了列表对象的引用,而变量b依然是字符串对象’abcde’的引用,并且字符串对象的引用计数为由2变为1.
如果此时再对b进行重新赋值,字符串对象‘abcde’的引用计数就会变为0,然后这个对象就被垃圾回收了。
【妹子说】这一集感觉聊的很细,我来总结一下:给一个变量赋一个新值,并不是替换原始对象,而是让这个变量去引用完全不同的另一个对象,而原来对象的引用计数会随之减1。好好梳理梳理这些概念吧,很有用的~
Python爱好者社区历史文章大合集:
Python爱好者社区历史文章列表(每周append更新一次)
关注后在公众号内回复“课程”即可获取:
小编的Python入门免费视频课程!!!
【最新免费微课】小编的Python快速上手matplotlib可视化库!!!
崔老师爬虫实战案例免费学习视频。
陈老师数据分析报告制作免费学习视频。
玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。