Python中的指针?`x.pointerDest = y.pointerDest`?

4 投票
3 回答
3326 浏览
提问于 2025-04-16 11:49

我把我之前的问题拆成几个部分,因为它实在太复杂了,详细内容可以在这里找到。这个问题和这个回答以及这个回答有关。我在尝试理解指针,但不确定在Python中是否存在指针。

# Won't change x with y=4
>>> x = 0; y = x; y = 4; x
0

# Won't change y
>>> x = 0; y = x; x = 2; y
0

#so how can I change pointers? Do they even exist in Python?
x = 0
y.pointerDestination = x.pointerDestination   #How? By which command?
x = 2
# y should be 0, how?

[更新 2:已解决]

可能存在矛盾的说法,比如说Python中没有指针。Python没有“指向”简单标量值的概念。最后一句话是否意味着指向其他东西的指针是存在的,这样就否定了第一句话?

3 个回答

1

在Python中没有指针这个概念。取而代之的是一种叫做引用的东西(虽然它们在实现上常常用指针,但和C++中的引用不同的是,Python的引用并不意味着按引用传递)。每个变量都存储着一个指向其他地方(堆内存)分配的对象的引用。每个集合也存储着指向其他地方分配的对象的引用。对象的每个成员同样存储着指向其他地方分配的对象的引用。

简单来说,表达式x会返回存储在x中的引用——使用这个引用的人无法知道它是来自一个变量。你无法获取到一个变量的链接(与其内容相对),也就是说无法追踪这个变量的变化。对项(x[y] = ...)和成员(x.y = ...)的赋值在一个方面是不同的:它们调用方法并改变现有对象,而不是覆盖一个本地变量。这种区别在处理作用域时特别重要,但你可以使用这两种方式来模拟不可变类型的可变性(正如@Greg Hewgill所示),并在函数边界之间共享状态变化(例如def f(x): x = 0不会改变任何东西,但def g(x): x.x = 0会改变)。不过,这并不能完全模拟按引用传递——除非你把每个变量替换成一个包装对象,这个对象的唯一目的是持有一个可变的val属性。这就相当于在C语言中通过指针模拟按引用传递,但要麻烦得多。

2

不要把指针和引用搞混。它们不是一回事。指针其实就是指向一个对象的地址。在Python中,你并不能直接访问对象的地址,只能访问它们的引用。

当你把一个对象赋值给一个变量时,其实是把这个对象的引用赋给了变量。

x = 0
# x is a reference to an object `0`
y = [0]
# y is a reference to an object `[0]`

在Python中,有些对象是可变的,这意味着你可以改变这个对象的属性。还有一些对象是不可变的,意味着你不能改变它们的属性。

int(一个标量对象)是不可变的。你不能改变一个int的任何属性(也就是不能修改)。

# suppose ints had a `value` property which stores the value
x.value = 20 # does not work

list(一个非标量对象)是可变的。你可以改变列表中的单个元素,让它指向其他东西。

y[0] = 20 # changes the 0th element of the list to `20`

在你展示的例子中:

>>> x = [0]
>>> y = [x]

你并不是在处理指针,而是在处理指向某些值的列表的引用。x是一个包含单个整数0的列表。y是一个列表,它包含了对x所指向的内容的引用(在这个例子中,就是列表[0])。

你可以这样改变x内容

>>> print(x)
[0]
>>> x[0] = 2
>>> print(x)
[2]

你可以通过y的引用来改变x所指向的列表的内容

>>> print(x)
[2]
>>> print(y)
[[2]]
>>> y[0][0] = 5
>>> print(x)
[5]
>>> print(y)
[[5]]

你也可以改变y内容,让它指向其他东西:

>>> print(y)
[[5]]
>>> y[0] = 12345
>>> print(x)
[5]
>>> print(y)
[12345]

这基本上和Java或C#等语言的语义是一样的。你并不直接使用指向对象的指针(虽然在底层实现中确实使用了指针),而是使用对象的引用。

6

在Python中,标量对象是不可变的。这意味着一旦你创建了一个标量对象,比如数字或字符串,你就不能改变它的值。如果你使用的是非标量对象,比如列表,你可以这样做:

>>> x = [0]
>>> y = x
>>> y[0] = 4
>>> y
[4]
>>> x
[4]
>>> x is y
True

Python没有“指针”这个概念来指向简单的标量值。

撰写回答