前言

在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基础系列讲解—动态类型语言的特点的更多相关文章

  1. Python基础系列讲解——继承派生和组合的概念剖析

    Python作为一门面向对象的语言,它的面向对象体系中主要存在这么两种关系,一个是“类”和“实例”的关系,另一个是“父类”和“子类”的关系. 所谓“类”是从一堆对象中以抽象的方式把相同的特征归类得到的 ...

  2. Python基础系列讲解——try_except异常处理机制

    在Python编程中不可避免的会出现错误,在调试阶段出现语法之类的错误时,Pycharm会在Debug窗口提示错误,但是程序在运行时由于内部隐含的问题而引起错误,会导致程序终止执行.比如以下例程中,使 ...

  3. Python基础系列讲解——random模块随机数的生成

    随机数参与的应用场景大家一定不会陌生,比如密码加盐时会在原密码上关联一串随机数,蒙特卡洛算法会通过随机数采样等等.Python内置的random模块提供了生成随机数的方法,使用这些方法时需要导入ran ...

  4. Python基础系列讲解——TCP协议的socket编程

    前言 我们知道TCP协议(Transmission Control Protocol, 传输控制协议)是一种面向连接的传输层通信协议,它能提供高可靠性通信,像HTTP/HTTPS等网络服务都采用TCP ...

  5. Python基础系列讲解-自动控制windows桌面

    原链接:https://zhuanlan.zhihu.com/p/73001806 在使用PC时与PC交互的主要途径是看屏幕显示.听声音,点击鼠标和敲键盘等等.在自动化办公的趋势下,繁琐的工作可以让程 ...

  6. Python基础系列讲解——时间模块详解大全之time模块

    Python中提供处理时间日期相关的内置模块有time.datetime和calendar. time模块中大多数函数调用了所在平台C library 的同名函数,因此更依赖于操作系统层面,所以tim ...

  7. Python 语言特性:编译+解释、动态类型语言、动态语言

    1. 解释性语言和编译性语言 1.1 定义 1.2 Python 属于编译型还是解释型? 1.3 收获 2. 动态类型语言 2.1 定义 2.2 比较 2. 动态语言(动态编程语言) 3.1 定义 3 ...

  8. python基础系列教程——Python3.x标准模块库目录

    python基础系列教程——Python3.x标准模块库目录 文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwrap:文本填充 unicodedata ...

  9. 【转】解析JDK 7的动态类型语言支持

    http://www.infoq.com/cn/articles/jdk-dynamically-typed-language Java虚拟机的字节码指令集的数量自从Sun公司的第一款Java虚拟机问 ...

随机推荐

  1. 【转】Spring Boot干货系列:(六)静态资源和拦截器处理

    前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类WebMvcConfigurerAdapter. 正文 前面章节我们也有简单介绍过SpringBoot中对静态资源的默认支持 ...

  2. MySQL(二)索引背后的数据结构及算法原理

    本文转载自CodingLabs,原文链接 MySQL索引背后的数据结构及算法原理 目录 摘要 一.数据结构及算法基础 1. 索引的本质 2. B-Tree和B+Tree 3. 为什么使用B-Tree( ...

  3. PAT乙级1016

    1016 部分A+B (15 分)   正整数 A 的“D​A​​(为 1 位整数)部分”定义为由 A 中所有 D​A​​ 组成的新整数 P​A​​.例如:给定 A=3862767,D​A​​=6,则 ...

  4. Handlebars模板引擎

    介绍 Handlebars 是 JavaScript 一个语义模板库,通过对view和data的分离来快速构建Web模板.它采用"Logic-less template"(无逻辑模 ...

  5. IntelliJ IDEA使用技巧整理

    1 .写代码时用 Alt-Insert ( Code|Generate… )可以创建类里面任何字段的 getter 与 setter 方法. 2 .右键点击断点标记(在文本的左边栏里)激活速查菜单,你 ...

  6. Flask租房项目总结

    该Flask项目历时3天,开发小组6人,目的是开发一个租房web项目,该项目采用前后端分离模式. Flask租房项目总结 分析需求文档,需要完成的功能模块有: 登陆注册 首页展示,首页搜索 详情展示, ...

  7. 初学node.js-MongoDB安装和环境服务配置(4)

    一.mongoDB安装: (1)官网下载,我的是windows64位系统,目前最新版mongodb-win32-x86_64-2008plus-ssl-4.0.9-signed.msi 安装步骤不说了 ...

  8. MAC & Xcode 快捷键的使用

    "磨刀不费砍材工",在熟悉了MAC 和 Xcode 快捷键后一定可以帮助我们更快捷方便的开发程序 MAC 快捷键: command + Q = 退出应用程序 command + c ...

  9. PHP各环境下的伪静态配置

    一.Apache的伪静态配置 1.网站根目录下需要有 .htaccess 文件,没有则自己创建一个,内容为 <IfModule mod_rewrite.c> RewriteEngine o ...

  10. [收藏转]由于CredSSP加密Oracle修正 导致远程桌面报错处理

    原文:https://blog.csdn.net/lanwilliam/article/details/80346792 由于win103月份的一个更新,导致mstsc突然无法连接服务器了,报错如标题 ...