我试图通过将其ascii值移动2来改变字符串中的字符(使用ord()
)。
这就是我使用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'
。这两个代码都不是一样的吗?为什么没有第一个工作?
答案 0 :(得分:3)
在for循环块中,
for i in s:
i=chr(ord(i)-2)
i
指向可迭代对象s
的每个元素。但是当您为i
分配内容时,它只会指向已分配的项目,而原始项目保持不变。您可以使用此程序进行确认。
s='cde'
for i in s:
print id(i)
i=chr(ord(i)-2)
print id(i)
print map(id, s)
id
函数返回python对象的唯一ID。在每次迭代时,它会打印两个ID。第一个对应于字符串中元素的id,但第二个对应于指定的元素。
另一方面,list comprehension创建一个新列表并加入。这就是为什么改变会反映在那里。
答案 1 :(得分:3)
在你的例子中
s='cde'
for i in s:
i=chr(ord(i)-2)
print s
变量i
接收字符串项的值的副本(读取:"字符")。更改i
不会更改该字符串项。
答案 2 :(得分:2)
字符串是不可变的,但是不是 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']
列表对象是可变的,但是分配仍然将没有更改为l
,因为i=chr(ord(i)+1)
只是让i
引用另一个字符串
<强> 2。在这种情况下,我们如何更改/替换列表中的值?
列表是可变的,您可以使用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
答案 3 :(得分:0)
您的第一个不修改字符串。循环变量(在您的情况下为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