Python递归函数未声明global却修改全局矩阵变量的原因排查
为什么Python函数内未声明global也能修改全局列表?
核心原因:你混淆了「重新绑定变量」和「修改可变对象内部内容」两种操作
global关键字的作用范围非常明确:仅当你要在函数内部为全局变量重新赋值(也就是修改变量本身的指向,让它关联到新的对象)时,才需要声明global。
你当前的操作不属于这种情况:
- 列表是Python中的可变对象,你将全局变量
m作为参数传入函数时,函数的形参m和全局的m指向内存中同一个列表对象 - 你代码里的
m[y][x] = 0、m[y][x] = m[y-1][x]都属于修改该列表对象的内部元素,并没有给m这个变量本身重新赋值,自然不需要声明global,修改也会同步到所有指向该对象的变量上。
这个现象和递归完全无关,哪怕你写个最简单的修改列表元素的函数,也会出现同样的效果:
test_list = [1,2,3] def modify(lst): lst[0] = 999 modify(test_list) print(test_list) # 输出 [999,2,3],原列表已经被修改
解决方案:避免修改原对象
如果你希望函数只返回新矩阵、不改动原全局矩阵,只需要在操作前对传入的矩阵做深拷贝即可:
import copy def pop(x,y, m): """ 若仍在边界内,将m[x][y-1]的值赋给m[x][y] 若m[x][y-1]不存在,将m[x][y]设为0 """ # 深拷贝生成独立的新矩阵,后续操作都在新矩阵上执行 new_m = copy.deepcopy(m) def inner_pop(x, y): if y == 0: # 到达顶部,填充0 new_m[y][x] = 0 return new_m[y][x] = new_m[y-1][x] inner_pop(x, y-1) inner_pop(x,y) return new_m # 测试 m = [[1,2,3,4], [1,3,4,2], [4,1,2,4], [1,2,3,1]] a = pop(2,2, m) # 此时a是修改后的结果,全局m保持原值不变
内容的提问来源于stack exchange,提问作者JoeTheShmoe
相关产品推荐
相关产品推荐

