人们有时会问:“Python 中有指针吗?”作为一个老年工程师,我本不愿给出那种模棱两可的答案,但这个问题的确取决于你对“指针”的定义。
经典的指针定义是:一种存储其他数据地址的变量,你可以通过它来操作那些数据。用非常宽泛的伪代码表示,大概是这样的:
myvar = SOMETHING; mypointer = get_address_of(myvar); print(get_value_via_pointer(mypointer)); ## output is SOMETHING
这样的定义非常有用,因为我们可以用指针来引用数据,根据我们所需要的任何逻辑,在代码的某处设置一个指针,用它指向某数据。而后可以在无需了解它所指的具体内容或决策过程的情况下,在别处使用该指针。指针提供的这种间接性让我们能够分离关注点,编写更模块化的代码。
许多编程语言都提供了类似的指针功能。例如,在 C 语言中,get_address_of()
操作由取址符&
完成,而get_value_via_pointer()
操作由解引用符*
实现,前面的代码片段会写成:
int myvar = 17; int *mypointer = &myvar; print_int(*mypointer); // outputs 17
其他如 C++、C#、Go、Rust、Pascal 乃至 Fortran 等语言也具有类似的能力。
那么 Python 呢?从某种意义上说,Python 没有像这样的指针概念。你可以说 Python 的id()
函数提供了get_address_of()
功能,因为它至少在 CPython 中返回数据的内存地址:
myvar = 17 mypointer = id(myvar) # ** not useful
但 Python 没有逆操作:没有get_value_via_pointer()
能让你根据mypointer
获取到myvar
。
因此,Python 没有经典的这一对操作来显式地使用指针。但另一方面,Python 中的每个变量都是一个指针,因为 Python 中的变量是对象的引用名。
在Python中,上述简单示例看起来像这样:
myvar = 17 mypointer = myvar print(mypointer) # outputs 17
当有人问 Python 是否有指针时,或许最好的答案是:它不像其他一些语言那样有显式的指针,但一切隐含地都是指针。所以当你需要时,你拥有指针的力量:你可以拥有多个数据结构,然后将变量赋值为你选择的一个,并在之后使用该变量。这样其实已经实现了指针中的“数据(which data)”与“操作(work with the data)”的分离。
注意:
-
一些语言如 C 还允许指针进行算术运算,以调整数组中一项到另一项的指针。Python 的引用不支持这一点。
-
Python的标准库提供了ctypes,非常适合与本地 C 代码交互,包括暴露 C 指针在内的细节。但这并不算作 Python 有显式指针的功能。