Python 列表理解和for循环的结果不一样

Python 列表理解和for循环的结果不一样,python,Python,我试图通过使用ord将ascii值移位2来更改字符串中的字符。 这就是我使用for循环的方式: s='cde' for i in s: i=chr(ord(i)-2) print s 这只是给了我原来的字符串--“cde”而不是“abc”。然而,使用列表理解给了我正确的答案: str='cde' str=''.join([chr(ord(i)-2) for i in str]) print str 结果:“abc”。这两个代码块不是在做相同的事情吗?为什么第一个不起作用?在for循环

我试图通过使用ord将ascii值移位2来更改字符串中的字符。 这就是我使用for循环的方式:

s='cde'
for i in s:
    i=chr(ord(i)-2)
print s
这只是给了我原来的字符串--“cde”而不是“abc”。然而,使用列表理解给了我正确的答案:

str='cde'
str=''.join([chr(ord(i)-2) for i in str])
print str

结果:“abc”。这两个代码块不是在做相同的事情吗?为什么第一个不起作用?

在for循环块中

for i in s:
    i=chr(ord(i)-2)
我指向iterable对象s的每个元素。但是,当您将某个内容分配给i时,它只是指向分配的项,而保留原始项不变。你可以用这个程序来确认这一点

s='cde'
for i in s:
    print id(i)
    i=chr(ord(i)-2)
    print id(i)
print map(id, s)
函数返回python对象的唯一id。在每次迭代中,它打印两个ID。第一个对应于字符串中元素的id,但第二个对应于指定的元素

另一方面,列表理解创建一个新的列表,并将其连接起来。这就是为什么变化会反映在这里。

在您的示例中

s='cde'
for i in s:
    i=chr(ord(i)-2)
print s

变量i接收字符串read:character的一个项的值的副本。更改i不会更改该字符串项。

您的第一次更改不会修改该字符串。在您的例子中,循环变量i没有引用从中生成它的字符串,因此更改它不会反映在不可变的字符串中,这可能有点牵强。例如:

s = "abc"
for index, char in enumerate(s):
    char = 'z'           #we assign tp the loop variable. the actual string is unchanged.
    print(char)          #prints 'z'
    print(s[index])      #prints the original char from the string, a -> b -> c
您的第二个示例直接指定给字符串,因此它被更改

为了让您的第一项技术发挥作用,请尝试以下方法:

s='cde'
temp = ''
for i in s:
    temp = str.join([temp, chr(ord(i)-2)])
s = temp

字符串是不可变的,但这不是for循环中赋值失败的原因,请参见下面的代码:

In [272]: l=list('asdf')

In [273]: l
Out[273]: ['a', 's', 'd', 'f']

In [274]: for i in l:
     ...:     i=chr(ord(i)+1)
     ...:     

In [275]: l
Out[275]: ['a', 's', 'd', 'f']
list对象是可变的,但赋值仍然不会将任何内容更改为l,因为i=CHORDI+1只是使i引用另一个字符串


二,。在这种情况下,我们如何更改/替换列表中的值

列表是可变的,您可以使用l[i]引用l中的项目,使用enumerate可以在迭代时获取索引:

In [299]: for i, v in enumerate(l):
     ...:     l[i]+='z'
     ...:     

In [300]: l
Out[300]: ['az', 'sz', 'dz', 'fz']
请注意,尽管l是可变的,但l[0]仍然是不可变的:

In [301]: l=list('asdf')

In [302]: id(l[0])
Out[302]: 33639888

In [303]: for i, v in enumerate(l):
     ...:     l[i]+='z'

In [304]: l
Out[304]: ['az', 'sz', 'dz', 'fz']

In [305]: id(l[0])  #what l[0] refers to has been changed
Out[305]: 110316288

不,他们不是。字符串是不可变的。@AshwiniChaudhary:没错,但即使s是一个列表,在这里它不会改变。@DSM你是对的,它没有。在这种情况下,我们如何更改/替换列表中的值?@VineetKaushik你通常不应该更改正在迭代的列表-只要创建另一个列表或使用列表理解,如果你需要它。@zhangxaochen谢谢+1.