Python中的指针?`x.pointerDest = y.pointerDest`?
我把我之前的问题拆成几个部分,因为它实在太复杂了,详细内容可以在这里找到。这个问题和这个回答以及这个回答有关。我在尝试理解指针,但不确定在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 个回答
在Python中没有指针这个概念。取而代之的是一种叫做引用的东西(虽然它们在实现上常常用指针,但和C++中的引用不同的是,Python的引用并不意味着按引用传递)。每个变量都存储着一个指向其他地方(堆内存)分配的对象的引用。每个集合也存储着指向其他地方分配的对象的引用。对象的每个成员同样存储着指向其他地方分配的对象的引用。
简单来说,表达式x
会返回存储在x
中的引用——使用这个引用的人无法知道它是来自一个变量。你无法获取到一个变量的链接(与其内容相对),也就是说无法追踪这个变量的变化。对项(x[y] = ...
)和成员(x.y = ...
)的赋值在一个方面是不同的:它们调用方法并改变现有对象,而不是覆盖一个本地变量。这种区别在处理作用域时特别重要,但你可以使用这两种方式来模拟不可变类型的可变性(正如@Greg Hewgill所示),并在函数边界之间共享状态变化(例如def f(x): x = 0
不会改变任何东西,但def g(x): x.x = 0
会改变)。不过,这并不能完全模拟按引用传递——除非你把每个变量替换成一个包装对象,这个对象的唯一目的是持有一个可变的val
属性。这就相当于在C语言中通过指针模拟按引用传递,但要麻烦得多。
不要把指针和引用搞混。它们不是一回事。指针其实就是指向一个对象的地址。在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#等语言的语义是一样的。你并不直接使用指向对象的指针(虽然在底层实现中确实使用了指针),而是使用对象的引用。
在Python中,标量对象是不可变的。这意味着一旦你创建了一个标量对象,比如数字或字符串,你就不能改变它的值。如果你使用的是非标量对象,比如列表,你可以这样做:
>>> x = [0]
>>> y = x
>>> y[0] = 4
>>> y
[4]
>>> x
[4]
>>> x is y
True
Python没有“指针”这个概念来指向简单的标量值。