更新 Python 中的列表:为什么我的 for 循环在一个函数中的范围显然是全局的?

Updating a list in Python: Why is the scope of my for-loop within a function apparently global?

我是一个绝对的Python-新手,我在使用以下功能时遇到了一些麻烦。我希望你能帮助我。非常感谢您的提前帮助!

我已经通过列表理解在一个目录中创建了一个 zip 文件列表:

zips_in_folder = [file for file in os.listdir(my_path) if file.endswith('.zip')]

然后我想定义一个函数,用“-”替换列表中每个元素中某个索引处的某个字符:

print(zips_in_folder)
def replacer_zip_names(r_index, replacer, zips_in_folder=zips_in_folder):
    for index, element in enumerate(zips_in_folder): 
        x = list(element)
        x[r_index] = replacer
        zips_in_folder[index]=''.join(x)
replacer_zip_names(5,"-")

print(zips_in_folder)

输出:

['12345#6', '22345#6']
['12345-6', '22345-6']

函数有效,但我无法理解:为什么我的函数会更新实际列表“zips_in_folder”。我认为函数内的“zips_in_folder”列表只是函数外实际列表的“影子”。在这种情况下,for 循环的范围是全局的而不是局部的吗?

在我写的其他函数中,变量的作用域总是局部的...

我几个小时以来一直在寻找答案,希望我的问题不是太明显! 再次感谢!

最佳 菲利克斯

一个简单的思考方式是列表是可变的,这意味着以下内容为真:

a = [1, 2, 3]
b = a           # a, b are referring to the same object
a[1] = 20       # b now is [1, 20, 3]

这是因为列表是 python 中的对象,而不是原始变量,所以该函数会更改“原始”列表,即它不会创建它的本地副本。

同样适用于任何 class,用户定义或其他:操作对象的函数不会复制该对象,它会更改传递给它的“原始”对象。

如果您了解 c++ 或任何其他低级编程语言,它与按引用传递相同。

这是一个相当中等的话题。在一行中:Python 是传递对象引用。

这是什么意思

zips_in_folder 是一个对象。一个对象有一个指向它在内存中的位置的引用(可以把它想象成一个地址)。要访问一个对象,您需要使用它的引用。 现在,这是关键部分:

For objects Python 传递它们的引用作为值

这意味着创建了对象的 引用 的副本,但同样,新引用指向内存中的相同位置。

因此,如果您使用引用的副本访问对象,那么原始对象将被修改。

在您的函数中,zips_in_folder 是一个变量,用于存储引用的新副本。 以下行使用新副本访问原始对象:

zips_in_folder[index]=''.join(x)

但是,如果您决定重新分配存储引用的变量,则不会对对象或其原始引用[=37]做任何事情=],因为你只是重新分配了存储引用副本的变量,你并没有修改原始对象。意思是:

def reassign(a):
  a = []

a = [1,0]
reassign(a)
print(a)  # output: [1,0]