分享

学了C再学Python,一定要了解变量的实现方式:引用语义和值语义

 山峰云绕 2018-09-05

https://www.toutiao.com/a6583429024326877700/



Python变量的对象都是对象,可以是基本整数、浮点数等类型的对象,也可以是组合类型的对象,如list等。程序中建立和使用的各种复杂对象,包括Python函数等,都是基本独立的存储块实现,通过链接相互关联。程序是里的名字(变量、参数、函数名等)关联着作为其值的对象,这种关系可以用赋值操作改变。

Python语言中变量的这种实现方式称为变量的引用语义,在变量里保存值(对象)的引用。采用这种方式,变量所需的存储空间大小一致,因为其中只需要保存一个引用。有些语言采用的不是这种方式,它们把变量的值直接保存在变量的存储区里,称为值语义。这样,一个整数类型的变量就需要保存一个整数所需的空间,一个浮点数变量就需要足够的空间存储一个浮点数。如果一个变量中需要保存很大的数据对象,它就需要占据更大的存储空间。例如C语言采用的就是变量的值语义。

C语言用指针实现引用关系。所以Python中变量与对象的引用关系类似于C语言的指针变量与指针指向的值的关系。

Python语言的实现基于一套精心设计的链接结构。变量与其值对象的关系通过链接的方式实现,对象之间的联系同样也通过链接。一个复杂对象内部也可能包含几个子部分,相互之间通过链接建立联系。如果一个list包含10个字符串,那么在实现中,在这个list对象里就会记录这10个字符串的链接关系。

在Python的数据结构中,对象分为不可变对象和可变对象。基本数据类型如int、float、bool等都是不可变对象。在结构数据类型中,元组tuple、str是不变对象。list、dict、set是可变对象,可变对象存储的元素的引用其实是没有改变的,改变的是其引用指向的值。

要实现对数据的存储和处理,就要“存得进去,取得出来”,还要考虑时间和空间效率。

使用变量(包括常量)和内存地址的对应关系,可以让没有意义且难记忆的地址通过变量或变量而变得有意义和好记。但地址是有线性关系的,这是编程需要利用的规律(如内存单元的索引,包括数字或关键字索引),这是编程语言(编译器)及操作系统需要考虑的,考虑以什么样的方式呈现在编程者面前。如C语言用指针,其它语言以隐式的引用。

我们知道,内存是一批线性排列的存储单元。对于集合类型,我们只要知道集合的第一个元素的地址,便可以推导出元素的存储地址。显然,序列类型中元素的线性关系可以用这种方式表示。这种存储方式要求元素存储在一起,如果在中间增加或删除一个元素,当存储的元素比较多时,效率会比较慢。如果要任意存储(是指不一定要存储在一起),如何能保证所有元素的都可以被访问到?我们可以联想到现实世界在仓库(假定仓库的每一个位置都是编地址码的)里存储物品的实际情况。如果要在仓库放客户存过来的一票货,这票货可能有几十件,你无法在仓库找到单独的一个位置,只能分开存放,要确保“随时快速找到某一件货”的原则,你可以将每一件货(编号)保存的位置记录下来,录入电脑,找某一编号的货时,便打查找到对应的货位(地址码)。还有一种方式,就是每一件的记录,另外再保存一个其下一件货的地址,这样只要知道了第一件货的位置,顺藤摸瓜下去,就可以找到需要找的货。对应到电脑中的数据存储,上面的方式其实就是顺序存储、映射存储、链式存储。顺序存储要求一个集合的数据元素存储在一起,映射存储就是每一个元素映射一个存储地址,链式存储就是每一个元素除了保存其自身的值以外,还额外保存相邻元素(后趋或前后趋)的地址或引用。这就是数据结构中的存储结构。

数据集合中元素的实际关系有一对一的线性关系,有一对多的层次关系(树型关系)和多对多的网状关系(图形关系)。线性关系好解决,内存单元本身就是线性结构的,所以数据元素存储在内存中就已经隐性地表示了数据元素的线性关系。但是图形关系就不行了,图形关系的集合数据除了要保存数据元素本身以外,还要把数据元素之间的联系也看作一种数据,显式地保存在内存中。如一个图形结构就要保存两个集合,一个是顶点集数据,一个产顶点相互连接的边集数据。这里所说的数据结构关系称为数据的逻辑结构。

最复杂的图形数据结构,如果采用链式存储,其数据量包括:顶点、边及数据的链接地址。最简单的线性结构,如果采用顺序存储,只需保存数据元素本身即可。

在值语义的C语言中,函数有参数传递有值传递和指针传递(C++中还有引用传递)一说。而在引用语言的Python语言中,所有的传递都是引用传递,但引用的对象有不变对象与可变对象的区别,当用不变对象的变量对形参赋值时,因对象的不变性,函数内、外的不变对象变量会开辟不同作用域的内存空间,因而彼此不会受到影响,而对于可变对象变量而言,因为其可变,所以当函数引用时,并不会开辟不同的内存空间,所以可以改变可变变量的元素指向的值。

下面通过一个实例来理解一下:

学了C再学Python,一定要了解变量的实现方式:引用语义和值语义

运行结果:

学了C再学Python,一定要了解变量的实现方式:引用语义和值语义

变量引用关系:

学了C再学Python,一定要了解变量的实现方式:引用语义和值语义

在Python中,一切都是对象,字面常量先分配内存单元ID,当这个字面常量赋值给变量时,变量存储这个ID,实现引用语义。

在C中,变量直接存储值,实现值语义,然后通过指针实现引用语义;

在C++中,变量直接存储值,实现值语义,然后通过指针和引用实现引用语义。

C++是C的延续与加强,而Python是另一种语言设计思路。

-End-

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多