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)
...