Python:列表项在for循环中没有更改
当以下代码没有达到我预期的效果时,我感到震惊:Python:列表项在for循环中没有更改,python,list,loops,Python,List,Loops,当以下代码没有达到我预期的效果时,我感到震惊: lines_list = ['this is line 1\n', 'this is line 2\n', 'this is line 3\n'] for line in lines_list: line = line.strip() 我当然希望列表中的每一项都变成“stripped”,即在本例中,没有尾随的'\n'字符,但它没有 print lines_list 输出: ['this is line 1\n', 'this is li
lines_list = ['this is line 1\n', 'this is line 2\n', 'this is line 3\n']
for line in lines_list:
line = line.strip()
我当然希望列表中的每一项都变成“stripped”
,即在本例中,没有尾随的'\n'
字符,但它没有
print lines_list
输出:
['this is line 1\n', 'this is line 2\n', 'this is line 3\n']
正如您所猜测的,我的问题是,在for
循环期间,是否有一种优雅的方法来更改列表项?我不想重复这个列表
编辑:
顺便提一下,在Perl或Java中,我的使用效果很好。Python是具有独特行为的
在Java中,这将起作用:
String[] lines = {"this is line 1\n", "this is line 2\n", "this is line 3\n"};
for (String line : lines) {
line = line.trim();
}
my @lines = ("this is line 1\n", "this is line 2\n", "this is line 3\n");
foreach my $line (@lines) {
$line =~ s/\s+$//;
$line =~ s/^\s+//;
}
在Perl中,这将起作用:
String[] lines = {"this is line 1\n", "this is line 2\n", "this is line 3\n"};
for (String line : lines) {
line = line.trim();
}
my @lines = ("this is line 1\n", "this is line 2\n", "this is line 3\n");
foreach my $line (@lines) {
$line =~ s/\s+$//;
$line =~ s/^\s+//;
}
您可以通过索引进行检查,并以这种方式就地修改
for i, _ in enumerate(lines_list):
lines_list[i] = lines_list[i].strip()
虽然我认为很多人更喜欢简单的复制列表,如果列表不是那么大,它会导致一个问题
lines_list = [line.strip() for line in lines_list]
问题是使用=
运算符重新分配变量行
,它不会影响原始字符串的内容。在以下情况下,新的python程序员同样经常感到惊讶:
for i in range(10):
print(i)
i += 1
打印数字0,1,2,3,4,5,6,7,8,9。这是因为for循环在每次迭代开始时将i
重新分配给范围中的下一个元素。这不完全是你的问题,但也很相似
因为您正在从文件中读取行,然后将它们剥离,所以您真正应该做的是
with open(file_name) as f:
lines_list = [line.strip() for line in f]
在您的示例中,
line
只是一个变量。它未连接到可能来自的列表。想一想,如果每个变量都修改它的原点,会出现什么问题
在python中,通常不会修改列表,但会创建一个新列表。因此有一种叫做列表理解的东西:
lines_list = [line.strip() for line in lines_list]
您确实忘了为某些内容指定新值(剥离字符串) 另一种方法是,如何以较短的方式将其分配给列表:
>>> lst = ['this is line 1\n', 'this is line 2\n', 'this is line 3\n']
>>> import string
>>> lst = map(string.strip, lst)
>>> lst
['this is line 1', 'this is line 2', 'this is line 3]
我同意,但我觉得它不那么优雅。另外,我猜(但没有证据)使用索引而不是迭代器访问列表项在性能上更昂贵。在我看来,您添加的新解决方案更漂亮。谢谢@用户3322273好奇的是,你是通过将文件读入列表来获得这些行的吗?Ryan的回答很酷。通常(取决于内存限制),在迭代时更改正在迭代的集合(事实上,某些语言,如C#,禁止并将通过编译时错误)不是一种好的做法,因为这会带来(有时)可以避免的复杂性(每次迭代都使用修改过的集合)。是的,但我不想让人们注意文件阅读,所以我在这里展示了一个硬编码列表。但是五年后还是一样的,但是java示例也没有修改原始的
行
,因为同样的原因,python示例五年后也没有修改,这对我来说真的很奇怪。由于字符串是不可变的,我不希望line=line.trim()
影响数组中的引用。这是相同的原因,因为您正在将line
更改为引用新字符串。即使使用可变类型,=
也不会更改左侧的对象,[]=
则不同。