我将两个ListNode
对象声明为head = curr = ListNode(0)
。现在,令我惊讶的是,他们都指向同一个地址:
>>> head
<__main__.ListNode object at 0x10bf271d0>
>>> curr
<__main__.ListNode object at 0x10bf271d0>
为什么? 为什么不像a = b = 4
?
因为,如果我对b
进行更改,a
不会受到影响。但是,如果我通过以下方式对curr
进行更改,head
可以对其进行跟踪:
>>> curr.next = ListNode(1)
>>> curr = curr.next
>>> head
<__main__.ListNode object at 0x10bf271d0>
>>> curr
<__main__.ListNode object at 0x10bf27190>
>>> head.next
<__main__.ListNode object at 0x10bf27190>
我知道head
和curr
是通过引用指针(地址(来声明的,a
和b
是通过引用值来声明的。是吗?
如果是,我如何控制用 ref 到 value 声明的内容和用 ref 声明到指针(地址(的内容?
上面使用的ListNode
类如下:
>>> class ListNode(object):
... def __init__(self, x):
... self.val = x
... self.next = None
...
编辑:解释这个问题与可变v/s不可变不可变与可变类型有何不同。
这个问题解决了变量的绑定和引用,而另一个问题严格讨论了Python中的可变和不可变对象及其差异。虽然后者确实讲述了变量的引用以解释可变与不可变,但它并没有解决这个问题中提出的疑问,因此,对于社区来说,那些困惑的观察者会知道由于这个问题而引用的概念。
python 中的整数是不可变的。当您执行以下操作时:
a = b = 4
a = a + 1
在这种情况下,a
和b
是独立的,因为一旦你尝试改变a
,你实际上是在将一个新的int
对象绑定到a
。您实际上永远不会更改整数,只是重新绑定。
当您执行以下操作时:
head = curr = ListNode(0)
创建一个ListNode
对象,并将引用head
和curr
绑定到该对象。它们都指向内存中的同一位置,就像整数一样。但是,由于您的类是可变的,因此在发生突变时没有理由重新绑定。这是预期行为。
编辑 - 只是为了使整数不变性和重新绑定更清晰一点:
a = b = 4
print(f"ID of 'a': {id(a)}")
print(f"ID of 'b': {id(b)}")
a += 1
print("nAfter adding +1 to 'a'...")
print(f"ID of 'a': {id(a)}")
print(f"ID of 'b': {id(b)}")
输出:
ID of 'a': 1853646048
ID of 'b': 1853646048
After adding +1 to 'a'...
ID of 'a': 1853646064
ID of 'b': 1853646048
您可以看到,尝试改变a
不会更改基础整数对象 - 它只是将a
重新绑定到新的整数对象。
不像
a = b = 4
?
相反。就像它一样:
a = b = 4
print(id(a))
# 4552081648
print(id(b))
# 4552081648
因为,如果我对
b
进行更改,a
不会受到影响。但是,如果我通过以下方式对curr
进行更改,head
可以跟踪它:
通过重新分配b
来更改它,从而将名称重新绑定到新值:
b = 5
print(id(b))
# 4552081680
然而,在你修改curr
时,你没有重新绑定curr
所以它一直引用相同的值。
与常见的误解相反,这与不变性无关:您当然可以将名称重新绑定到可变值:
head = curr = ListNode(0)
head = ListNode(0)
head
# <__main__.ListNode at 0x10bf27118>
curr
# <__main__.ListNode at 0x10bf271d0>
。如您所见,head
和curr
现在引用不同的值。