Python中函数内修改类实例为何无法同步到调用函数作用域
Python参数传递机制说明
Python不存在传统编程语言里的“按值传递”或“按引用传递”,采用的是**传对象引用(又称传赋值)**机制:调用函数时,会把外部传入的对象的内存地址,绑定到函数内部的形参变量上。形参和外部实参最初指向同一个对象,但对形参变量本身的重新赋值,不会对外部作用域的实参产生任何影响。
两类操作的效果差异
你遇到的问题本质是混淆了「修改对象本身」和「给形参变量重新赋值」的区别:
- 如果操作是修改对象的属性、修改可变对象内部的元素(比如给list追加元素、修改ListNode实例的next属性):因为形参和实参指向内存里的同一个对象,这类修改会同步反映到外部作用域。
- 如果操作是给形参变量直接赋值(比如你写的
l = l.next、res = res.next):本质只是修改函数内部局部变量的指向,让这个局部变量从原来指向的对象,改成指向另一个对象,这个改动完全不会触碰外部作用域的变量。
你的代码里,外部while循环的判断条件依赖ll的指向,但你在函数内部对形参l做l = l.next的赋值,根本不会改变外部ll的指向,ll永远指向链表的第一个节点,循环条件永远为真,自然会陷入无限循环。
除此之外你代码里还有一个完全同源的bug:函数内的res = res.next同样不会改变外部res变量的指向,就算循环能终止,你得到的复制链表也只有一个节点,根本无法形成完整的链式结构。
修复方案
不要尝试在被调用函数内部通过给形参重新赋值的方式,移动外部作用域的遍历指针,两种可行的实现方式:
- 把遍历指针的移动逻辑放在同一个作用域内实现,示例代码:
class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next # 构建原链表 ll = ListNode(1) ll.next = ListNode(2) def copy_linked_list(origin_head): dummy = ListNode() cur_res = dummy cur_origin = origin_head while cur_origin: cur_res.next = ListNode(cur_origin.val) cur_res = cur_res.next cur_origin = cur_origin.next return dummy.next new_ll = copy_linked_list(ll)
- 如果必须拆分为独立的单步处理函数,让函数返回更新后的指针位置,在外部作用域接收返回值完成指针移动:
def append_new_node(res_cur, origin_cur): res_cur.next = ListNode(origin_cur.val) return res_cur.next, origin_cur.next res_dummy = ListNode() res_cur = res_dummy cur_origin = ll while cur_origin: res_cur, cur_origin = append_new_node(res_cur, cur_origin) new_ll = res_dummy.next
内容的提问来源于stack exchange,提问作者Asmita Poddar
相关产品推荐
相关产品推荐

