由 Python 中一切皆对象说开去
在 Python 中,一切皆对象意味着什么呢?这个问题从我一开始学习编程一直持续到现在,随着自己对编程有了越来越深入和清晰的了解,同时开始学习其它语言时,自己对这个问题的答案也一直在变动着。
在 Python 中,我们写下的任何一个变量都是某种对象的「实例」,这种对象可以是 Python 内建好的,也可以是我们自己定义的。
然后,一般情况下,我们在创建一个对象实例的同时,也会对这个实例进行某种操作,最基本的操作是「赋值」。
这里的「赋值」还有几种情况:
- 新建一个变量并赋值
- 这种情况下,是给实例一个标志符,以便后续再取到这个实例进行某种操作
- 具体的,在 Python 中,是新建一个 name ,并将实例 bind 到这个 name 上,日后通过 name 就可以间接操作实例
- 这被称为「引用」
- 赋到某个变量的内部,这个就很简单了,就是成为目标变量的一部分
这自然衍生出下一个问题:
将某个变量 name 赋值给另一个变量 name 时,发生了什么?
= 右侧是表达式,Python 会先通过 name 取到对象实例,然后计算出表达式的值,这个值同样是一个实例,然后将实例绑定到左侧 name 上。
引用和指针
通过以上的分析,似乎 Python 的引用特别像 C 或 C++ 中的指针,但确实不一样。
我对引用和指针的理解
指针和引用是用来干什么的?这应该很明确:获取变量并对变量进行某种操作。
指针相当于是一种间接操作,改变指针内地址处的数据。此外,我们也要注意到,指针本身也是变量,这个变量也暴露在我们的操纵范围内,从而,很自然的,会有指向指针变量的指针变量。
引用呢?引用只是一个名字,一个标志符,引用本身不是变量,因为我们无法获取某个引用的值,或者改变某个引用的值,同样的,我们也没有指向引用的引用。一切引用都是直接指向一个对象实例,这种指向关系是一个表,由 Python 维护,而且这个指向关系还有作用域的区分,并不只有一个表,而是有很多表。
再回到指针上,假设现在有一个指针变量 a,我们把这个 a 传给某个函数,并在这个函数内部通过 a 的地址获取到 a 指向的值,并改变它。
这段描述是 C 中操纵数据的典型方式,可我们知道 C 的函数传参都是 「传值」,所以事实上这里的说法是有一定问题的:
在函数内部,我们只是获取到了指针变量 a 的一个副本,我们通过这个副本内部存储的地址操纵我们想要改变的数据。假如我们在函数内部完成了上述操作之后,把指针变量 a 改变,之后返回到函数外部,原有指针变量 a 的值并不受影响。
但 Python 中,并不是传值,也不是传引用,而是在函数内部创建了一个新的关系映射表,我们可以通过这个引用获取并修改那个对象,同时,对对象的修改是对外可见的。但是类似 C 中的情况,如果我们在函数内部命令本来指向函数参数的引用标志符指向了其它变量的话,我们就等同于破坏掉了这个关系指向,此时如果没有其它关系指向可用,我们就失去了对函数参数的获取途径。
此外这个函数内部的关系映射表,也是局部的,这也是为什么在 Python 中,我们能使用一个外部变量的值,但却无法直接改变它的原因,必须通过 global 关键词,引入新的而且是全局的关系映射才可以改变全局变量。
今天先到这里。
不知是该恭喜,还是该怎样,总之阅读到该文的,你是第 人。每一次刷新,都是不同的自己。