为何Python部分全局变量无需global即可在函数中访问?
Python全局变量访问差异的原因解析
核心原因:变量的"读取"与"赋值"操作的作用域规则
Python对函数内变量的作用域判断逻辑很明确:
- 如果函数内只读取变量的值,不对变量本身进行赋值,Python会自动向上查找作用域,找到全局变量就直接使用,不需要
global声明。 - 如果函数内存在对变量本身的赋值操作(比如
var = ...或var += ...),Python会默认这个变量是局部变量,此时如果在赋值前尝试读取它,就会抛出UnboundLocalError。
针对你的代码的具体分析
为什么dp可以正常访问
dp是列表类型的全局变量,你在函数内的所有操作都没有给dp变量本身重新赋值:
print(dp):直接读取全局的dp变量dp[i] == 0:读取dp列表的元素值dp[i] = 1:修改dp列表的元素,只是改变列表内部的内容,不是重新定义dp这个变量
Python会认为你只是在操作全局列表的内容,不是创建局部变量,所以不需要global声明就能正常访问。
为什么curStr会报错
curStr是字符串类型的全局变量,你在函数内存在明确的赋值操作:
curStr += cards[i]:等价于curStr = curStr + cards[i],是给curStr变量本身赋值curStr = curStr[:-len(cards[i])]:直接给curStr变量赋值
Python看到这些赋值操作后,会默认curStr是局部变量,但函数开头的print(curStr)在局部的curStr被赋值前就执行了,所以抛出UnboundLocalError——局部变量还没被赋值就被引用。
解决方法
方法1:用global声明全局变量
在函数开头明确声明curStr是全局变量,告诉Python不要把它当成局部变量:
import sys input = sys.stdin.readline n = int(input()) k = int(input()) cards = [input().rstrip() for _ in range(n)] dp = [1] * n res = set() curStr = "" def concat(cards, k, n, count): global curStr # 声明curStr为全局变量 print(dp) print(curStr) if count == k: res.add(curStr) return for i in range(n): if dp[i] == 0: curStr += cards[i] dp[i] = 1 concat(cards, k, n, count + 1) dp[i] = 0 curStr = curStr[:-len(cards[i])] concat(cards, k, n, 0) print(len(res))
方法2:避免全局变量,改用参数传递
更推荐的写法是把curStr作为递归参数传递,这样不需要依赖全局变量,代码逻辑更清晰:
import sys input = sys.stdin.readline n = int(input()) k = int(input()) cards = [input().rstrip() for _ in range(n)] dp = [1] * n res = set() def concat(cards, k, n, count, curStr): print(dp) print(curStr) if count == k: res.add(curStr) return for i in range(n): if dp[i] == 0: new_str = curStr + cards[i] dp[i] = 1 concat(cards, k, n, count + 1, new_str) dp[i] = 0 concat(cards, k, n, 0, "") print(len(res))
内容的提问来源于stack exchange,提问作者YSEO
相关产品推荐
相关产品推荐

