004.动态类型

本系列文章是我我的学习《python学习手册(第五版)》的学习笔记,其中大部份内容为该书的总结和我的理解,小部份内容为相关知识点的扩展。html

非商业用途转载请注明做者和出处;商业用途请联系本人(gaoyang1019@hotmail.com)获取许可。java

基础概念的解释

首先咱们来解释一些基础概念,看不懂的能够跳过,这对于初学者不是很重要。python

强类型语言和弱类型语言

首先,强弱类型语言的区分不是看变量声明的时候是否显式的定义数据类型。程序员

强类型语言,定义是任何变量在使用的时候必需要指定这个变量的类型,并且在程序的运行过程当中这个变量只能存储这个类型的数据。所以,对于强类型语言,一个变量不通过强制转换,它永远是这个数据类型,不容许隐式的类型转换。好比java,python都属于强类型语言。web

强类型语言在编译的时候,就能够检查出类型错误,避免一些不可预知的错误,使得程序更加安全。缓存

与之对应的是弱类型语言,在变量使用的时候,不严格的检查数据类型,好比vbScript,数字12和字符串3进行链接,能够直接获得123。再好比C语言中int i = 0.0是能够经过编译的。安全

另外知乎上关于相关问题 rainoftime 大神也有相关解答,没有查到权威解释,对大神的解答存疑,可是能够参考,帮助咱们理解。数据结构

动态类型语言和静态类型语言

动态类型和静态类型的区别主要在数据类型检查的阶段。app

动态类型语言:运行期间才去作数据类型的检查。在动态类型语言中,不须要给变量显式的指明其数据类型,该语言会在第一次赋值的时候,将内部的数据类型记录下来。编辑器

静态类型语言,在编译阶段就进行数据类型检查。也就是说静态类型语言,在定义变量的时候,必须声明数据类型。

这里有个比较经典的图:

各种语言的定义

堆和栈

首先,堆儿(很差意思,这里不该该带儿化音...),堆(heap)和栈(stack)的概念在不一样范畴是有不一样含义的。

在数据结构中,堆指的是知足父子节点知足大小关系的一种彻底二叉树。栈指的是知足后进先出(LIFO),支持pop和push两种操做的一个“桶”(原本想说序列,可是不知道准不许确,因此说了个桶...)

在操做系统中,堆儿和栈指的是内存空间。

栈,和数据结构中的栈差很少,是一个LIFO队列,由编译器自动分配和释放,主要用来存放函数的参数值,局部变量的值等内容。

堆,通常由程序员分配和释放,固然,像java和python这类语言也有自动垃圾回收的机制。这个咱们在后面会讲到。

变量、对象和引用

python中的变量声明是不须要显式的指定类型的,但这并不代表python是一个弱类型语言。

好比,咱们的一条简单的赋值语句a=3,那么接下来python编译器会作哪些事情呢?

建立变量和字面量:

建立一个字面量3(若是这个字面量尚未被建立过的状况下)

建立一个名称叫a的变量。通常咱们理解在这个变量a第一次被赋值的时候就建立了它。(实际python解释器在运行代码以前就会检测变量名)

检查变量类型:

python中类型是针对对象而言的,并非针对变量名而言的。 对象会包含两个重要的头部信息,一个是类型标志符,一个是引用计数器。

变量名并不会限制变量的类型。也就是说这个

a 它只是一个名字,具体“关联”什么类型的变量,这个是没有限制的。

变量的使用

当变量出如今表达式中的时候,它就会被当前引用的对象所代替。

仍是说这个例子,若是在以后的代码中使用了a,好比

a+1那么这里的a就会被指向3这个字面量

简单总结,当咱们执行a=3的时候,实际作了三件事:

建立一个对象实例,3

建立一个变量,a

将变量名a引用到对象实例3上

image-20201214204037907

这里提到了一个概念,引用。 引用其实就是一种关系,是经过内存中的指针所实现的。

好嘞,这里又出现了一个新的概念,指针。 指针这个东西,简单来讲能够理解为内存地址的一个指向。就是对初学者很差解释(主要是我懒得解释,就是属于那种懂的不须要讲,不懂的一时半会讲了也是不懂,可是随着学习的深刻,慢慢就理解了的东西。。。)

变量的类型

首先,python是一个强类型语言,这是毫无疑问的。 可是python不须要显式的声明变量类型。 这是由于python的类型是记录在对象实例中的。

在前面咱们讲到过,python中的对象会包含两个重要的头部信息:

类型标志符(type designator):用来标识这个对象的类型

引用计数器(reference counter): 代表有多少个变量引用到了这个对象上,用于跟踪改对象应该什么时候被回收

由于对象的这个机制,python中的变量声明的时候,就不须要再指定类型了。 也就是说变量名与变量类型是无关的。

a=1

a='spam'

a=1.123

并且如上所示,同一个变量名能够赋值给不一样类型的对象实例。

共享引用

这里提出一个问题,以下代码:

In [6]: a=3

In [7]: b=a

In [8]: a='spam'

那么在通过这一系列操做以后,a和b的值分别是啥?

In [9]: a

Out[9]: 'spam'

In [10]: b

Out[10]: 3

首先咱们来看,在执行a=3和b=a以后,发生了什么

image-20201214210333750

a=3根据以前的介绍,比较好理解了。b=a实际上变量名b只是复制了a的引用,而后b也引用到了对象实例3上。那在以后这一句a='spam'又发生了什么?

image-20201214210854202

这个图就说的很清楚了,在咱们执行了a='spam'以后,a被指向了另一个对象。

搞清楚了这个以后,咱们再来看下一个例子:

a=3

b=a

a=a+3

这个前两句就不须要解释了,第三句a=a+3 其实一眼就能够看出来,此时a是6。这个就涉及到前面说的,当a出如今表达式中的时候,它就会“变成”它所引用的对象实例。a=a+3也就是会变成3+3 计算后得出新的对象实例6,而后变量a引用到6这个对象上。

「在原位置修改」

关于共享引用,这里看一个特殊的例子:

In [16]: L1=[1,2,3]

In [17]: L2=L1

In [18]: L1[0]=1111

In [19]: L1

Out[19]: [1111, 2, 3]

In [20]: L2

Out[20]: [1111, 2, 3]

按照以前的剧本,L2和L1都是指向列表[1,2,3]这个对象的,那为何在咱们修改L1[0] 这个元素以后,为何L2也跟着发生变化了呢?

我本身画了图,从这个图能够看出来,实际上对于L1和L2的共享引用来看,并无违反咱们上面说的共享引用的原则。只是对于序列中元素的修改,L1[0]会在原位置覆盖列表对象中的某部分值。

image-20201214212940939

那么问题来了若是在修改L1[0]以后,并不想L2的值受到影响,那该怎么办?

简单

把列表原本来本的复制一份就行了。 复制的办法有三种:

第一种针对列表而言,能够直接建立一个完整的切片,本质上是一种浅拷贝。

In [32]: L1=[[1,2,3],4,5,6]

In [33]: L2=L1[:]

In [34]: L2

Out[34]: [[1, 2, 3], 4, 5, 6]

In [37]: L1[2]='aaa'

In [38]: L2

Out[38]: [[1111, 2, 3], 4, 5, 6]

In [39]: L1

Out[39]: [[1111, 2, 3], 4, 'aaa', 6]

第二种,浅拷贝,以下面这个例子中的D1.copy()

In [26]: D1={a:[1,2,3],b:3}

In [27]: import copy

In [28]: D2=D1.copy()

In [29]: D2

Out[29]: {6: [1, 2, 3], 3: 3}

In [30]: D1[a][0]=1111

In [31]: D2

Out[31]: {6: [1111, 2, 3], 3: 3}

第三种,深拷贝,以下D2=copy.deepcopy(D1)

In [41]: import copy

In [45]: D1={'A':[1,2,3],'B':'spam'}

In [46]: D1

Out[46]: {'A': [1, 2, 3], 'B': 'spam'}

In [47]: D2=copy.deepcopy(D1)

In [48]: D2

Out[48]: {'A': [1, 2, 3], 'B': 'spam'}

In [49]: D1['A'][0]=1111

In [50]: D1

Out[50]: {'A': [1111, 2, 3], 'B': 'spam'}

In [51]: D2

Out[51]: {'A': [1, 2, 3], 'B': 'spam'}

我相信,看到这里,对于深拷贝和浅拷贝有些读者已经明白了,可是有些读者仍是迷糊的。 这里简单说一下,

浅拷贝:只拷贝父对象,不会拷贝对象内部的子对象。

深拷贝:彻底拷贝父对象和子对象。

浅拷贝

深拷贝

「关于相等」

先看一个例子

In [59]: L1=[1,2,3]

In [60]: L2=L1

In [61]: L1==L2

Out[61]: True

In [62]: L1 is L2

Out[62]: True

In [66]: L1=[1,2,3]

In [67]: L2=[1,2,3]

In [68]: L1==L2

Out[68]: True

In [69]: L1 is L2

Out[69]: False

从上面这个例子就能够看出来,==比较的是值,is 实际比较的是实现引用的指针。

对象的垃圾收集和弱引用

垃圾回收机制也是一件很复杂的事情,可是python编译器能够本身去处理这玩意儿。 因此在初级阶段,咱们不须要过多关注这玩意儿。 知道有这么个东西就够了。

这里简单的介绍下,python中的垃圾回收就是咱们所谓的GC,靠的是对象的引用计数器。引用计数器为0的时候,这个对象实例就会被释放。对象的引用计数器能够经过sys.getrefcount(istance)来查看。

In [70]: import sys

In [72]: sys.getrefcount(1)

Out[72]: 2719

引用计数器的引入能够很好的跟踪对象的使用状况,可是在某些状况下,也可能会带来问题。 好比循环引用的问题。

以下代码:

In [73]: L =[1,2,3]

In [74]: L.append(L)

固然,正常人确定不会写出这种智障代码,可是在一些复杂的数据结构中,子对象互相引用,就可能会形成死锁。好比:

In [1]: class Node:

...:   def __init__(self):

...:     self.parent=None

...:     self.child=None

...:   def add_child(self,child):

...:     self.child=child

...:     child.parent=self

...:   def __del__(self):

...:     print('deleted')

...:

这里咱们定义了一个简单的类。这时,若是咱们建立一个节点,而后删除它,能够看到,对象被回收,而且准确的打印出了deleted。

In [2]: a=Node()

In [3]: del a

deleted

那么,像下面这个例子,在删除a节点以后,貌似没有触发垃圾回收,只有手动的gc以后,这两个对象实例才被删除。

在删除a以后,没有触发垃圾回收,是由于它俩互相引用,实例的引用计数器并无置0 。

那在手动gc以后,因为python的gc会检测这种循环引用,并删除它。

In [4]: a=Node()

In [5]: a.add_child(Node())

In [6]: del a

In [7]: import gc

In [8]: gc.collect()

deleted

deleted

Out[8]: 356

A和B的关系

那么若是使用弱引用的话,效果就不同了

In [9]: import weakref

...:

...: class Node:

...:   def __init__(self):

...:     self.parent=None

...:     self.child=None

...:   def add_child(self,child):

...:     self.child=child

...:     child.parent=weakref.ref(self)

...:   def __del__(self):

...:     print('deleted')

...:

In [10]: a=Node()

In [11]: a.add_child(Node())

In [12]: del a

deleted

deleted

因此这里就能够看出来,所谓弱引用,其实并无增长对象的引用计数器,即便弱引用存在,垃圾回收器也会当作没看见。

弱引用通常能够拿来作缓存使用,对象存在时可用,对象不存在的时候返回None。这正符合缓存有则使用,无则从新获取的性质。

python动态数据类型_[python学习手册-笔记]004.动态类型相关推荐

  1. python数值类型不包含复数_[python学习手册-笔记]003.数值类型

    003.数值类型 ❝ 本系列文章是我个人学习<python学习手册(第五版)>的学习笔记,其中大部分内容为该书的总结和个人理解,小部分内容为相关知识点的扩展. 非商业用途转载请注明作者和出 ...

  2. 语句与语法笔记:学会python中_doc_和pydoc——python学习手册笔记之3

    标题## 语句与语法:学会python中的_doc_和pydoc--python学习手册笔记之3 光看书不练习很难学好python,光看书不做点学习笔记,恐怕连书本的东西也是半知半解,不知所云.这手册 ...

  3. CCNA精品学习资料汇总(学习手册+笔记+题库)

       CCNA精品学习资料汇总(学习手册+笔记+题库) CCNA认证标志着具备安装.配置.运行中型路由和交换网络,并进行故障排除的能力.获得CCNA认证的专业人士拥有相应的知识和技能,能够通过广域网与 ...

  4. python官方手册笔记_Python学习手册笔记

    Python学习手册(原书第4版)Mark Lutz 著 第一部分 使用入门 >> orthogonal >> 交互提示模式下编写代码 >> "%&quo ...

  5. python 自定义数据类型_【整理合集,建议收藏】Python数据类型(一)

    一.数据类型 在python这门语言中,数据类型分为两种. 内置的和自定义的. 内置的包括 数字 . 字符串 . 布尔 . 列表 . 元组 . 字典 . Bytes . 集合 这些常用的以 及一些不太 ...

  6. 不属于python的数据类型_下列________不是Python的数据类型。

    [判断题]已知 x, y = 3, 5,那么执行x, y = y, x 之后,x的值为15. [多选题]Python 中对变量描述正确的选项是( ) [单选题]字符串是一个连续的字符序列,用_____ ...

  7. python 画蜘蛛_如何学习 R 绘图?

    写在前面:为啥不用excel绘制这些图,用PoweBI,帆软BI等可视化软件来绘图,不是更方便吗?的确,这些工具都很方便,但同时,它们显得很呆,不够灵活,更为致命的是,它们绘制出的图形,分辨率不够,用 ...

  8. python 英语培训_英语学习与Python编程语言学习相辅相成(三十一)

    最近在学习Python编程语言,Python编程语言并不难学,入门很容易,编程的语言用英语编,编写的第一个程序是" Hello World",你好,世界. 在学Python编程语言 ...

  9. 关于python的浮点数类型、以下_python入门教程Python 浮点数数据类型详解 [学习 Python 必备基础知识][看此一篇就够了]...

    python基础语法.jpg 您的"关注"和"点赞",是信任,是认可,是支持,是动力...... 如意见相佐,可留言. 本人必将竭尽全力试图做到准确和全面,终其 ...

  10. php java python容易入门_先学习Python之后再学习PHP与java会更好吗

    学过python语言之后在去学习PHP javascript 这些编程语言是不是会更好的能快速理解, 有python基础之后,再去学习php语言 理解上 是不是更方便上手, 我现在主要想学习专研 PH ...

最新文章

  1. php高手要学哪些_如何样深入学习php,成为php高手
  2. 自动化办公 Python 操控 Word
  3. Spring 4 CustomEditorConfigurer Example--转
  4. HDU 5115 Dire Wolf 区间dp
  5. 【133】常见问题解答
  6. 系统性能测试--杨建旭
  7. Springboot第二篇:与前端fetch通信(附springboot解决跨域方法)
  8. 一款问答APP的产品需求文档(PRD)
  9. shallow clone
  10. Python中文编码过程中遇到的一些问题
  11. 如何编写一个抢购bot_如何编写一个SkyWalking插件
  12. POST 请求出现异常!java.io.IOException: Server returned HTTP response code: 400 for URL
  13. mysql into outfile语法_select into outfile
  14. python实战代码目录信息
  15. 提前防止Non-PIE错误,检测app是否包含PIE标志
  16. GridView中使用DropDownList的OnSelectedIndexChanged事件
  17. 《计算机网络(第七版)谢希仁 编著》部分课后答案
  18. 1.Spring Boot使用Apache Curator实现服务的注册和发现「第四章 ZooKeeper Curator应用场景实战」「架构之路ZooKeeper理论和实战」
  19. API调用展示,淘宝、天猫、拼多多商品页面详情API,APP端原数据参数返回
  20. requests.exceptions.SSLError: HTTPSConnectionPool(host=‘edith.xiaohongshu.com‘, port=443): Max retri

热门文章

  1. Linux 内核编程总结
  2. HTML 实现扫雷游戏
  3. 文字时钟罗盘动态html代码_文字时钟罗盘动态html代码工具-文字时钟APP最新版下载-游戏窝...
  4. 这是我对智能制造的所有理念
  5. 拓扑图是用什么软件画的?
  6. cad填充图案乱理石_CAD实用填充图案129种下载_CAD实用填充图案129种官方下载-太平洋下载中心...
  7. 白话空间统计十六:增量空间自相关
  8. sql-server 不允许保存更改,解决办法
  9. Java课程设计-基于Swing的文本编辑器
  10. 【毕设教程】物联网/嵌入式/单片机毕业设计项目开发流程