我在python中创建了一个链表,并创建了一个指向同一节点的指针变量。
但是,当我尝试更新指针时,链表不会更新。 它仅在我使用原始符号时更新。 以下是关注的三行,然后是代码片段:
pointer = self.storage[index]
pointer = pointer.next #does not work
self.storage[index] = self.storage[index].next #DOES work.
def remove(self, key):
pair = LinkedPair(key,None)
index = self._hash_mod(pair)
pointer = self.storage[index]
prev = None
while pointer:
if pointer.key == pair.key:
if prev is None: #at the beginning of the linked list, set the head to equal the next value
print(self.storage[index] == pointer) #true
self.storage[index] = self.storage[index].next
pointer = pointer.next
# pointer = pointer.next
break
# self.display(pointer,prev,' pointer == pair')
prev.next = pointer.next
del pointer
break
else:
prev = pointer
pointer = pointer.next
# self.display(pointer,prev,' post shifting')
# self.storage[index] = self.storage[index].next
return -1
python 中的变量只是对象的名称,分配给它们只会更改由该名称指定的对象。
但是,当指派给列表的元素时,您将更改列表中该位置所引用的对象。
因此:
pointer = self.storage[index] # 1
pointer = pointer.next # 2
self.storage[index] = self.storage[index].next # 3
(1( 使pointer
成为在storage[index]
引用的对象的名称
(2(在赋值=
的右侧,查找pointer
引用对象的name
属性。这是self.storage[index].name
.赋值将使pointer
变量引用self.storage[index].name
。要更新self.storage
列表,您需要对列表对象本身进行操作。相反,pointer
所引用的self.storage[index]
只是"某个对象"。您甚至无法从那里返回列表,因此无法在此处更改列表。
(3(但是,在这里,您正在更改列表self.storage
,此时替换index. You could have done
self.storage[index] = pointer'处的元素,具有相同的效果。
当然,python 在引擎盖下使用引用(或指针(。my_list[1] = obj
没有为obj
分配空间,它会存储对它的引用。但是局部变量和全局变量不是引用,它们是名称。
最后,全局和局部命名空间只是将变量名称映射到对象。它们通常只是普通的字典。您可以通过调用globals()
和locals()
来查看这些内容。或者,您可以通过更改该字典来"实现"变量赋值:
foo = 1
globals()["foo"] = 2
print(foo) # --> 2
Python 对变量的赋值不同于对可变对象(如列表或字典(的赋值。让我们考虑以下语句:
a = 1 # 1
b = [1] # 2
b[0] = 2 # 3
前两个作业也在做同样的事情。它们正在创建(或更新(a
和b
的全局变量,并分别将它们映射到int
对象1
和list
对象[1]
。您将拥有:
globals()
{
...
"a": 1,
"b": [1]
...
}
第三个任务完全不同。这种类型的赋值实际上是由左侧的对象实现的。从文档中:
当目标是可变对象(属性引用、订阅或切片(的一部分时,可变对象最终必须执行赋值并决定其有效性,并且如果赋值不可接受,则可能会引发异常。
这意味着第三条语句由列表对象本身实现。现在 python 中的列表保留对对象的引用(它不会复制对象(。b[0]
在表达式中使用时,由列表对象的特殊方法实现,并将返回列表引用的位置 0 的对象。b[0] = 2
实际上是调用列表对象的特殊方法,将索引 (0( 和目标对象 (2( 作为参数,列表实现决定它如何更新自身:它将索引 0 处的引用更改为新对象。
这种差异嵌入在python的赋值语句中。我也喜欢你的完整参考资料。
更多详情:
- https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
- https://docs.python.org/3/tutorial/classes.html#a-word-about-names-and-objects
- https://docs.python.org/2.0/ref/assignment.html