更新 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]
我是一个绝对的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]