You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:39:02