Python 为什么我的(局部)变量的行为像一个全局变量?

Python 为什么我的(局部)变量的行为像一个全局变量?,python,list,global-variables,Python,List,Global Variables,我不使用全局变量,也从不显式定义全局变量,但我的代码中似乎有一个全局变量。你能帮我把它做成本地的吗 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

我不使用全局变量,也从不显式定义全局变量,但我的代码中似乎有一个全局变量。你能帮我把它做成本地的吗

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为了回答我自己的第二个问题,区别似乎是在第一个代码中没有显示列表方法,而在第二个代码中缺少列表方法

当您找到_minX时,您将向对象X传递一个列表(在本例中为该函数)。如果该函数改变列表(例如,通过附加到列表),则为“是”,它将影响原始对象。Python不会仅仅因为将对象传递给函数而复制对象。

如果确实找到了_minX,则会将对象X传递给函数(在本例中是一个列表)。如果该函数改变列表(例如,通过附加到列表),则为“是”,它将影响原始对象。Python不会因为将对象传递给函数而复制对象。

将对象传递给Python函数时,不会复制对象,而是传递指向该对象的指针

这是有意义的,因为它大大加快了执行速度——在长列表的情况下,不需要复制它的所有元素

但是,这意味着当您修改传递的对象(例如,您的列表X)时,即使在函数返回后,修改也会应用于该对象

例如:

def foo(x):
    x.extend('a')
    print x

l = []
foo(l)
foo(l)
将打印:

['a']


['a','a']

将对象传递给python函数时,不会复制该对象,而是传递指向该对象的指针

这是有意义的,因为它大大加快了执行速度——在长列表的情况下,不需要复制它的所有元素

但是,这意味着当您修改传递的对象(例如,您的列表X)时,即使在函数返回后,修改也会应用于该对象

例如:

def foo(x):
    x.extend('a')
    print x

l = []
foo(l)
foo(l)
将打印:

['a']


['a','a']

Python列表是可变的,也就是说,它们可以更改,并且在find_min函数调用中使用algo确实会更改X的值,也就是说,它是列表的按引用传递。例如,请参见。

Python列表是可变的,即它们可以更改,并且在find_min函数调用中使用algo确实会更改X的值,即列表是按引用传递的。例如,请参见。

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

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

当您在嵌套列表上操作时,应该使用copy模块中的deepcopy函数来创建列表的副本,您可以在不影响函数之外的任何内容的情况下自由地进行更改。内置的list函数也可以用于复制列表,但它只创建浅层副本,这不是嵌套列表所需要的,因为内部列表仍然只是指向相同对象的指针

from copy import deepcopy

def algo (X):
    X = deepcopy(X)
    ...

正如其他人已经指出的,问题在于列表是作为函数的引用传递的,因此函数体中的列表与作为参数传递给它的列表是同一个对象。因此,您的函数执行的任何突变都可以从外部看到

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

当您在嵌套列表上操作时,应该使用copy模块中的deepcopy函数来创建列表的副本,您可以在不影响函数之外的任何内容的情况下自由地进行更改。内置的list函数也可以用于复制列表,但它只创建浅层副本,这不是嵌套列表所需要的,因为内部列表仍然只是指向相同对象的指针

from copy import deepcopy

def algo (X):
    X = deepcopy(X)
    ...