Python基础系列讲解—动态类型语言的特点
前言
在C语言中变量所分配到的地址是内存空间中一个固定的位置,当我们改变变量值时, 对应内存空间中的值也相应改变。在Python中变量存储的机制是完全不一样的,当给一个变量赋值时首先解释器会给这个值分配内存空间,然后将变量指向这个值的地址,那么当我们改变变量值的时候解释器又会给新的值分配另一个内存空间,再将变量指向这个新值的地址,所以和C语言相比,在Python中改变的是变量所指向的地址,而内存空间中的值是固定不变的。
例程介绍
我们可以通过id方法查看变量的内存地址的方式来进行验证。以下先以Python的int类型为例,可以看到执行 i += 1 后,变量i的内存地址会发生变化,事实上 i += 1 并不是在原有变量i的地址上加1,而是重新创建一个值为6的int对象,变量i则引用了这个新的对象,因此当变量i和变量j的值相同时会指向同个内存地址 。同样以Python的float 类型为例也验证了这个变量存储管理的机制。
#int
i = 5
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
i += 1
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
j = 5
print "j ---> ",j
print "id(j) ---> ",hex(id(j))
______________________
i ---> 5
id(i) ---> 0xa26f880
i ---> 6
id(i) ---> 0xa26f874
j ---> 5
id(j) ---> 0xa26f880
#float
i = 1.5
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
i += 1
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
j = 1.5
print "j ---> ",j
print "id(j) ---> ",hex(id(j))
______________________
i ---> 1.5
id(i) ---> 0x9e86c8c
i ---> 2.5
id(i) ---> 0x9e86cac
j ---> 1.5
id(j) ---> 0x9e86c8c
接下来以Python的list类型为例,可以看到list变量i在append之后,仍然指向同一个内存地址,而j、k的值虽然相同,但是指向的内存地址却不同。我们通过j = k 的赋值语句可以让j、k指向同一个内存地址,对j、k任意一个list变量进行修改,都会影响另外一个list变量的值。比如j变量append(4)时,同时对k变量也产生影响,查看j、k的内存地址,发现它们仍然指向了同个内存地址。
#list
i = [1, 2, 3]
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
i.append(4)
print "i ---> ",i
print "id(i) ---> ",hex(id(i))
j = [1.5, 2.5, 3.5]
print "j ---> ",j
print "id(j) ---> ",hex(id(j))
k = [1.5, 2.5, 3.5]
print "k ---> ",j
print "id(k) ---> ",hex(id(k))
j = k
print "j ---> ",j
print "id(j) ---> ",hex(id(j))
print "k ---> ",j
print "id(k) ---> ",hex(id(k))
j.append(4)
print "j ---> ",j
print "id(j) ---> ",hex(id(j))
print "k ---> ",j
print "id(k) ---> ",hex(id(k))
______________________
i ---> [1, 2, 3]
id(i) ---> 0xb73fa1acL
i ---> [1, 2, 3, 4]
id(i) ---> 0xb73fa1acL
j ---> [1.5, 2.5, 3.5]
id(j) ---> 0xb6fed06cL
k ---> [1.5, 2.5, 3.5]
id(k) ---> 0xb6fed04cL
j ---> [1.5, 2.5, 3.5]
id(j) ---> 0xb6fed04cL
k ---> [1.5, 2.5, 3.5]
id(k) ---> 0xb6fed04cL
j ---> [1.5, 2.5, 3.5, 4]
id(j) ---> 0xb6fed04cL
k ---> [1.5, 2.5, 3.5, 4]
id(k) ---> 0xb6fed04cL
刚才讲到Python的int类型的两个变量值相同时,Python解释器并不会分别为两个变量申请内存,而是优化的将他们指向同个内存地址。但这里有个例外的情况,当变量s1和s2 存储20个char时,Python仍然将两个变量引用指向了相同内存地址,但当存储为21个char时,Python为s2开辟了新的内存。厦门叉车多少钱
s1 = 'a' * 20
s2 = 'a' * 20
print hex(id(s1)), hex(id(s2))
0xb7075320L 0xb7075320L
s1 = 'a' * 21
s2 = 'a' * 21
print hex(id(s1)), hex(id(s2))
0xb70752f0L 0xb7075350L
总结
根据以上的这些例子,我们可以知道Python中的对象分为可变类型和不可变类型,列表、字典是可变类型,而整数、浮点、短字符串、元组等是不可变类型。可变类型的变量赋值与我们了解的C语言机制相同,而不可变类型的变量赋值时,实际上是重新创建一个不可变类型的对象,并将原来的变量重新指向新创建的对象,当然如果没有其他变量引用原有对象时,原有对象就会被回收。这也是Python作为动态类型语言的特点,即变量不需要预先声明类型,当变量在赋值时解释器会根据值的类型创建对应的内存空间进行存储,并将变量指向这个地址空间即可,比如运行a=1时,解释器将变量指向整形值1的地址,当运行a=0.1时,解释器将变量指向浮点值0.1的地址。
说明:此处的例程测试环境为Ubuntu 16.04 LTS 32 位,不同的环境下测试结果可能会由于解释器的优化不同而有所不同。比如有网友发现解释器为两个相同浮点类型值的变量分配了不同的内存空间。
Python基础系列讲解—动态类型语言的特点的更多相关文章
- Python基础系列讲解——继承派生和组合的概念剖析
Python作为一门面向对象的语言,它的面向对象体系中主要存在这么两种关系,一个是“类”和“实例”的关系,另一个是“父类”和“子类”的关系. 所谓“类”是从一堆对象中以抽象的方式把相同的特征归类得到的 ...
- Python基础系列讲解——try_except异常处理机制
在Python编程中不可避免的会出现错误,在调试阶段出现语法之类的错误时,Pycharm会在Debug窗口提示错误,但是程序在运行时由于内部隐含的问题而引起错误,会导致程序终止执行.比如以下例程中,使 ...
- Python基础系列讲解——random模块随机数的生成
随机数参与的应用场景大家一定不会陌生,比如密码加盐时会在原密码上关联一串随机数,蒙特卡洛算法会通过随机数采样等等.Python内置的random模块提供了生成随机数的方法,使用这些方法时需要导入ran ...
- Python基础系列讲解——TCP协议的socket编程
前言 我们知道TCP协议(Transmission Control Protocol, 传输控制协议)是一种面向连接的传输层通信协议,它能提供高可靠性通信,像HTTP/HTTPS等网络服务都采用TCP ...
- Python基础系列讲解-自动控制windows桌面
原链接:https://zhuanlan.zhihu.com/p/73001806 在使用PC时与PC交互的主要途径是看屏幕显示.听声音,点击鼠标和敲键盘等等.在自动化办公的趋势下,繁琐的工作可以让程 ...
- Python基础系列讲解——时间模块详解大全之time模块
Python中提供处理时间日期相关的内置模块有time.datetime和calendar. time模块中大多数函数调用了所在平台C library 的同名函数,因此更依赖于操作系统层面,所以tim ...
- Python 语言特性:编译+解释、动态类型语言、动态语言
1. 解释性语言和编译性语言 1.1 定义 1.2 Python 属于编译型还是解释型? 1.3 收获 2. 动态类型语言 2.1 定义 2.2 比较 2. 动态语言(动态编程语言) 3.1 定义 3 ...
- python基础系列教程——Python3.x标准模块库目录
python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...
- 【转】解析JDK 7的动态类型语言支持
http://www.infoq.com/cn/articles/jdk-dynamically-typed-language Java虚拟机的字节码指令集的数量自从Sun公司的第一款Java虚拟机问 ...
随机推荐
- leetcode 141. Linked List Cycle 、 142. Linked List Cycle II
判断链表有环,环的入口结点,环的长度 1.判断有环: 快慢指针,一个移动一次,一个移动两次 2.环的入口结点: 相遇的结点不一定是入口节点,所以y表示入口节点到相遇节点的距离 n是环的个数 w + n ...
- [Luogu P1120]小木棍·加强版
#\(\mathcal{Description}\) 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过 \(50\) . 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开 ...
- C. Phone Numbers
http://codeforces.com/problemset/problem/940/C And where the are the phone numbers? You are given a ...
- 史上最详细的codeblocks安装教程!!!
codeblocks下载地址:https://www.cnblogs.com/yinbiao/p/8489748.html 下面是codeblocks具体的安装教程:
- Spring的简单应用与基本原理
一:重要概念理解 Spring很简单,一定不要想得太复杂,只是有些东西很拗口而已 1:IOC(控制反转) 概念:利用反射的原理将对象创建的权利交给了Spring,Spring在运行的时候根据配置文件( ...
- jQuery----事件绑定之动态添加、删除table行
在jquery中,给元素绑定事件,本文一共介绍三种方法,运用案例,针对最常用的on()方法,进行事件绑定操作. 事件绑定方法: ①$(element).bind() 参数:{ “事件名称1”:func ...
- Qt中插入html样式
Qt中引入html调节样式 HTML 设置行间距字体高度和颜色 <html><head/><body><p style=\"height:16px; ...
- 复制文件到IDE等工具出现乱码解决方案
首要的解决方案是设置文件或者项目或者工作空间的编码,可以采用在文件上.项目上右键->properties进行设置 第二种方式是在editplus等编辑器里打开文件,然后打开文件之后点击菜单Fil ...
- 2017-2018-2 20155315《网络对抗技术》Exp3:免杀原理与实践
实验目的 通过本部分内容的学习,认识到杀软局限性,提高在工作生活中对于恶意软件防范能力. 教程 实验内容 使用msf编码器,msfvenom,veil-evasion,shellcode编程等免杀工具 ...
- linux 服务启动
在linux上部署java服务的时候,发现服务启动正常,但是[ps -ef|grep java].[jps]看不到服务的运行. 查资料发现,[Java -jar Test.jar & ...