指针是C和C++系语言的重要概念,其本质是保存另一个变量内存地址的变量(Pointers are variables that hold the memory address of another variable.)。某些情况下,使用指针可以提高代码的效率。但是,指针也往往会对初学者造成困扰,即使是老手,也经常会出现内存管理的问题。

象Java、Python之类的语言并没有明确的指针的概念。但Python中如果需要使用类似指针行为的时候,可以模拟出指针的效果,同时又不会陷入内存管理的噩梦。

Python中为什么没有指针

看起来指针似乎违背了Python设计之禅(Zen of Python)。指针会带来隐含的修改,对初学者来说显得比较复杂,而且也为访问非预期内存块之类的危险操作提供了手段。Python倾向于对用户屏蔽类似内存管理之类的实现细节,更注重语言的实用性,甚至都不太关心执行速度。

Python中的对象

在Python中,一切都是对象。可以通过提供的内置函数isinstance()进行验证:

>>> isinstance(1, object)

True

>>> isinstance(str, object)

True

>>> isinstance(list(), object)

True

>>> def func():

pass

>>> isinstance(func, object)

True

由此可见,Python中无论基本类型、类、类实例、自定义函数等都是对象。对象至少由三部分数据组成:

引用计数(Reference Count)

对象类型(Type)

对象值(Value)

其中引用计数用来进行内存管理;对象类型用于在Python本身的实现层(CPython)保证运行期的类型安全;对象值才是对象的真实数据。

要想拨开Python指针的层层迷雾,首先需要了解Python中的两类对象。

不可变对象与可变对象

顾名思义,不可变对象(Immutable Object)就是值不能改变的对象,象int、bool、float、str、tuple等都是不可变对象,相反,list、set、directory等都是可变对象(Mutable Object)。可以使用id()函数(返回对象的内存地址)、is(两个对象具有同一个内存地址时返回True,否则返回False)对此进行验证:

>>> x = 5

>>> id(x)

8791652754384

>>> x = x + 1

>>> id(x)

8791652754416

>>> s = 'Python'

>>> id(s)

31016864

>>> s += ' test'

>>> id(s)

52447280

>>> s[0] = 'p'

Traceback (most recent call last):

File "", line 1, in

s[0]='p'

TypeError: 'str' object does not support item assignment

>>> lt = [1, 2, 3]

>>> id(lt)

52176968

>>> lt.append(4)

>>> id(lt)

52176968

>>> lt[0] = 5

>>> id(lt)

52176968

对整形对象x和字符串对象s进行操作后,得到了另一个对象(id函数返回了另一个值,说明对象的内存地址变了),对s[0]赋值时,得到TypeError,说明str对象的元素是不能进行赋值的;对list对象lt操作后,得到的还是原来的对象lt。这就说明x、s是不可变对象,lt是可变对象。

深入理解变量

Python中的“变量”与C和C++中的变量是截然不同的。甚至在Python中就不应该叫做变量(variables),而应该叫做名称(names)。听起来很怪异,但通常情况下把Python中的名称认为是变量也没关系,重要的是要理解它们的不同之处。

在C语言中,定义一个整形变量x:

int x = 2505;

挺简单的一句话,其背后发生了什么?

申请一个足够存储整型值的内存空间;

将2505赋值给该内存地址;

将x指向该值。

内存示意图如右图所示:

要修改x的值,只需要执行:

x = 2504;

该语句将新值2504赋给了变量x,覆盖了原值2505,更新后的内存显示了新值:

需要注意的是x的地址没有发生变化,仅是值变化了。这意味着x是内存地址,而不仅仅是个名字。 可以从另一个角度思考:x拥有一个内存地址(容器),该地址可以存储一个整形数,当将值赋给x时,相当于把这个值放进了x所拥有的内存地址。执行:

int y = x;

代码创建了一个新的容器(占用一段内存),并把x的值复制到该容器中,内存看起来是这样的:

虽然x的值复制给了y,但y拥有了一段新的内存,改写y值的时候对x没有影响。

再来看看Python中等价的代码:

x = 2505

除了不用声明x的类型外,和C代码没有区别。同样,代码的背后会执行以下操作:

创建一个PyObject对象(不同于Python中的对象,是CPython特有的Python中所有对象的基本结构。PyObject是C结构体,无法直接访问typecode和refcount等,不过通过sys.getrefcount()可以获取一些内部信息);

将PyObject对象的类型设置为整形;

将PyObject对象的值设置为2505;

创建一个称为x的名称;

将x指向新创建的PyObject对象;

将PyObject对象的引用计数加1。

内存示意如下:

与C语言中变量x拥有存储2505的内存块不同,Python中新创建的PyObject拥有这块内存,但是名称x并不拥有任何一块内存。

要将x的值修改为2504,执行:

x = 2504

这行代码会执行以下操作:

创建一个新的PyObject对象;

将新PyObject对象的类型设置为整形;

将新PyObject对象的值设置为2504;

将x指向新创建的PyObject对象;

将新PyObject对象的引用计数加1;

将旧PyObject对象的引用计数减1。

现在的内存示意图如下:

上图表明x指向一个对象的引用,而不拥有内存空间。x=2338语句不是一个赋值语句,而是将x绑定到一个引用。而且,旧的对象在内存中的引用计数为0,将等待被垃圾回收机制回收。

象C代码一样,将x赋值给一个新的名称y:

y = x

内存看起来就会是这个样子的:

并没有创建新的对象,只是将新名称y指向了同一个对象,可以通过 y is x 返回True确定x和y是同一个对象。同样,y也是不可变对象,如果对y进行操作,如y += 1,那么y就会绑定到一个新的对象,这时y is x就会返回False。

深刻理解Python中的对象是了解指针的重要基础,下篇文章中将会详细说明Python指针的具体内容。

python中有指针吗_Python中的指针——到底指什么(一)相关推荐

  1. python中的列表是指针吗_Python中的指针——到底指什么(二)

    在 Python中的指针--到底指什么(一) 中,我们知道在Python的一切都是对象,变量其实是指向PyObject对象的名称,对不可变变量进行操作后,名称指向了另一个PyObject. 扣留对象 ...

  2. python中有哪些赋值_python中的赋值,什么时候是传值什么时候是传址?

    参数的传递是通过自动将对象赋值给本地变量名来实现的.在函数运行时,函数头部的参数名是一个新的.本地的变量名,这个变量名是在函数的本地作用域内存在.参数的传递本质上就是python赋值的另一个实例而已. ...

  3. python中cls是什么意思_python中的cls到底指的是什么,与self有什么区别?

    作者:秦风 链接:https://www.zhihu.com/question/49660420/answer/335991541 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载 ...

  4. python算法和数据结构_Python中的数据结构和算法

    python算法和数据结构 To 至 Leonardo da Vinci 达芬奇(Leonardo da Vinci) 介绍 (Introduction) The purpose of this ar ...

  5. 纯虚函数--抽象类中的this到底指的是哪个子类实例呢

    抽象类中的this到底指的是哪个子类实例呢?请看代码: thread.h #ifndef __THREAD_H__ #define __THREAD_H__#include <iostream& ...

  6. python基本算法语句_Python中基本且又常用的算法

    这篇文章主要学习Python常用算法,Python常用排序算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algo ...

  7. python怎么清理垃圾_Python 中的“垃圾”是怎么回收的?

    前言 对于python来说,一切皆为对象,所有的变量赋值都遵循着对象引用机制.程序在运行的时候,需要在内存中开辟出一块空间,用于存放运行时产生的临时变量:计算完成后,再将结果输出到永久性存储器中.如果 ...

  8. python中 r什么意思_python中w、r指的是什么意思

    python中w.r指的是什么意思 发布时间:2020-11-20 10:54:44 来源:亿速云 阅读:100 作者:小新 这篇文章将为大家详细讲解有关python中w.r指的是什么意思,小编觉得挺 ...

  9. python基础知识测试题_Python中的单元测试—基础知识

    python基础知识测试题 Unit testing is the number one skill which separates people who just finished their de ...

最新文章

  1. 作者免费分享自己论文也不行,知名学术社交网站被判侵权,此前已下架20万余篇论文...
  2. 解读 | 2019 年 10 篇计算机视觉精选论文
  3. 那些实用与颜值齐飞的桌面!
  4. 第28天:js-Tab栏切换封装函数
  5. 深入理解Java幂等性
  6. LeetCode85 Maximal Rectangle
  7. centos7 服务器安装nginx,mysql,php
  8. 带默认参数值的函数 内联函数
  9. php截取字符串utf8,php自定义截取中文字符串-utf8版
  10. Python Tutorial 实践(2)
  11. 神经网络高维互信息计算Python实现(MINE)
  12. 计算机专业专科生毕业论文题目,★专科生计算机专业论文题目专科生计算机专业毕业论文题目大全专科生计算机专业论文选题参考...
  13. 如何ubuntu上安装tecplot,教你怎么创建图标哦!
  14. 线性代数知识点汇总:行列式和矩阵
  15. 【操作系统】Main Memory
  16. 读博与怠工(在北航硕博连读)——转载
  17. 互联网晚报 |12/2星期五 | 天猫向ofo及戴威索要5亿借款;优衣库创始人称在中国开3K家店还不够;国美电器回应已被破产清算...
  18. python多进程优化_Python 的多进程,考虑到会发生死进程,如何收敛结束,安全又方便?...
  19. www与m站间的转换
  20. 邓宁—克鲁格心理效应(达克效应)【转】

热门文章

  1. 手机wps怎么改html文件后缀名,手机WPS如何制作个人简历 WPS一键修改文档重命名方法分享...
  2. HbuilderX使用方法
  3. 直通车的转化怎样引流-纽黑文教学
  4. 起诉传音,华为为何会对一张壁纸要价2000万?
  5. Qt编译出错:During startup program exited with code 0xc0000135
  6. Photoshop cs5 基础教程 形状图层的布尔运算
  7. MATLAB中fplot函数,画出的figure中曲线存在空白的问题与解决方法。
  8. 统计英文字数c语言,用C语言作纯英文字数统计
  9. Android面试题和答案
  10. GBK编码和UTF-8编码的区别