我正在写一个ROT13函数,我不明白为什么以下不起作用:
def ROT(string):
# y = 0
for char in string:
x = ord(char)
if 97 <= x < 110 or 65 <= x < 78:
# string[y]=char.replace(char, chr(x+13))
char=char.replace(char, chr(x+13))
print(char)
# y+=1
elif x >= 110 or 78 <= x < 91:
# string[y]=char.replace(char, chr(x-13))
char=char.replace(char, chr(x-13))
print(char)
# y+=1
return string
string = ROT('Hello, lorem ipsum dolor sit amet')
print(string)
对函数的调用只是打印原始字符串。正如你在上面评论的行中看到的(如果读起来有点困难,请道歉),我试图定义一个变量y来通过字符串递增,然后访问它,但我遇到了运行时错误。我想出的解决方案是在函数的开头创建一个空字符串(从我的谷歌搜索来看,这似乎是大多数人使用的解决方案),但没有人解释为什么会这样。如果你要替换其中的每个字符,为什么返回原始字符串不起作用?
代码中的问题是您没有操作原始字符串。您只是在替换临时变量char
,而不是在原始字符串中。由于字符串在python中是不可变的,您可以尝试使用新字符串,而不是替换原始字符串,您可以将字符附加到新字符串中。类似:
modified_string = ""
for char in string:
#whatever condition
modified_string += #value to be added
您正在返回原始字符串,请尝试
def ROT(string):
# y = 0
result = ""
for char in string:
x = ord(char)
if 97 <= x < 110 or 65 <= x < 78:
# string[y]=char.replace(char, chr(x+13))
char=char.replace(char, chr(x+13))
result = result + char
print(char)
continue
# y+=1
elif x >= 110 or 78 <= x < 91:
# string[y]=char.replace(char, chr(x-13))
char=char.replace(char, chr(x-13))
print(char)
result = result + char
continue
# y+=1
result = result + char
return result
string = ROT('Hello, lorem ipsum dolor sit amet')
print(string)
其他人已经解决了主要问题——字符串是不可变的,所以在迭代时不能只切换一个字符。您可以使用bytearray
,但是。。。
FWIW,这是string.translate
:的一个很好的候选者
>>> import string
>>> fromchr = ''.join(chr(x) for x in range(97, 110) + range(65, 78))
>>> tochr = ''.join(chr(x+13) for x in range(97, 110) + range(65, 78))
>>> fromchr += ''.join(chr(x) for x in range(110, 256) + range(78, 91))
>>> tochr += ''.join(chr(x-13) for x in range(110, 256) + range(78, 91))
>>> trans = string.maketrans(fromchr, tochr)
>>> 'Hello, lorem ipsum dolor sit amet'.translate(trans)
'Uryyb, yberz vcfhz qbybe fvg nzrg'
这里最棒的是,创建翻译表需要花费1次时间。创建翻译表后,可以根据需要多次使用它。在优化的C代码中,您的翻译将在~O(n)时间内完成,所以如果您能得到一个更快(或更简单)的实现,我会感到惊讶。
这种方式甚至可以轻松击败内置的'rot13'
编解码器:
def rot13a(s):
return s.encode('rot13')
import string
fromchr = ''.join([chr(x) for x in range(97, 110) + range(65, 78)])
tochr = ''.join([chr(x+13) for x in range(97, 110) + range(65, 78)])
fromchr += ''.join(chr(x) for x in range(110, 256) + range(78, 91))
tochr += ''.join(chr(x-13) for x in range(110, 256) + range(78, 91))
trans = string.maketrans(fromchr, tochr)
def rot13b(s):
return s.translate(trans)
import timeit
test_string = 'Hello, lorem ipsum dolor sit amet'
print rot13a(test_string) == rot13b(test_string)
print timeit.timeit("rot13a(test_string)", "from __main__ import test_string, rot13a")
print timeit.timeit("rot13b(test_string)", "from __main__ import test_string, rot13b")
(我的结果):
True
1.52055001259 # rot13a
0.21444106102 # rot13b
请注意,这是python2.x代码。在python3.x中,不能只添加这样的范围,因为range
不再返回list
对象。但是,希望这个想法足够清晰