Skip to main content
 首页 » 编程设计

python之为什么我的(局部)变量表现得像全局变量

2025年05月04日17daizhj

我没有用到全局变量,也从未明确定义过全局变量,但我的代码中似乎有一个。你能帮我把它做成本地的吗?

def algo(X): # randomized algorithm 
    while len(X)>2: 
        # do a bunch of things to nested list X 
    print(X)  
    # tracing: output is the same every time, where it shouldn't be. 
    return len(X[1][1]) 
 
def find_min(X): # iterate algo() multiple times to find minimum  
    m = float('inf') 
    for i in some_range: 
        new = algo(X) 
        m = min(m, new) 
    return m 
 
X = [[[..], [...]], 
     [[..], [...]], 
     [[..], [...]]] 
 
print(find_min(X)) 
print(X)  
# same value as inside the algo() call, even though it shouldn't be affected. 

X 看起来像一个全局变量。随机算法 algo() 实际上只在第一次调用时执行一次,因为 X 保留其更改后的值,它永远不会进入 while 循环。 find_min 中迭代的目的因此被打败了。

我是 python 的新手,甚至是这个论坛的新手,所以如果我需要澄清我的问题,请告诉我。谢谢。

更新 非常感谢您到目前为止的所有回答。我几乎理解它,除了我以前做过这样的事情并且结果更快乐。你能解释一下为什么下面这段代码不同吗?

def qsort(X): 
    for ... 
        # recursively sort X in place 
        count+=1 # count number of operations 
    return X, count 
 
X = [ , , , ] 
Y, count = qsort(X) 
print(Y) # sorted 
print(X) # original, unsorted. 

谢谢。

更新 II 为了回答我自己的第二个问题,区别似乎是在第一个代码(未显示)中使用了列表方法,而在第二个代码中没有使用列表方法。

请您参考如下方法:

正如其他人已经指出的那样,问题在于列表作为函数的引用传递,因此函数体内的列表与您作为参数传递给它的对象是完全相同的对象。因此,您的函数执行的任何更改都可以从外部看到。

要解决这个问题,您的 algo 函数应该对它传递的列表的副本进行操作。

当你在嵌套列表上操作时,你应该使用 copy 模块中的 deepcopy 函数来创建你的列表的副本,你可以自由地改变它而无需影响你的功能之外的任何东西。内置的 list 函数也可以用来复制列表,但它只会创建浅拷贝,这不是你想要的嵌套列表,因为内部列表仍然只是指向相同的对象。

from copy import deepcopy 
 
def algo (X): 
    X = deepcopy(X) 
    ...