类属性按引用还是值赋值?结合LeetCode合并链表实例答疑
合并两个有序链表的变量赋值疑问
LeetCode 合并两个有序链表解决方案
class Solution(object): def mergeTwoLists(self, list1, list2): """ :type list1: Optional[ListNode] :type list2: Optional[ListNode] :rtype: Optional[ListNode] """ prehead = ListNode(-1) curr = prehead while list1 and list2: if (list1.val <= list2.val): curr.next = list1 list1 = list1.next else: curr.next = list2 list2 = list2.next curr = curr.next curr.next = list1 if list1 != None else list2 return prehead.next
疑问与示例
当执行
curr.next = list1后立刻执行list1 = list1.next时,为何curr.next没有指向list1.next?我认为这些对象及其属性是可变的,即变量赋值指向内存地址。为确认我对变量赋值的理解是否正确,请看以下示例:
a = [] b = [1] a = b b.append(2) print(a) print(b) print(id(a)) print(id(b))
在此示例中,修改b后a与b仍相等,上述链表示例与该列表示例有何不同?
核心差异解析
链表示例里的操作分两步:
curr.next = list1:将curr对象的next属性,指向当前list1变量引用的那个ListNode对象(暂称NodeA)。list1 = list1.next:这是给list1变量重新赋值,让它指向NodeA的next属性对应的对象(NodeB)。但这步只改变了list1变量的指向,完全不会影响curr.next——因为curr.next已经固定指向NodeA了,和list1现在指向谁没关系。
列表示例的操作逻辑不同:
a = b:让a和b两个变量同时指向同一个列表对象(暂称ListX)。b.append(2):这是直接修改ListX这个对象本身的内容,而非改变b变量的指向。因为a和b始终指向ListX,所以修改对象后,两个变量访问到的都是修改后的ListX,结果自然一致。
一句话总结:
- 链表示例改的是变量的指向,没碰对象本身,所以
curr.next不受影响; - 列表示例改的是变量指向的对象的内容,变量指向没变,所以两个变量的结果同步。
内容的提问来源于stack exchange,提问作者user23357772
相关产品推荐
相关产品推荐

