其他人已经解决了主要问题——字符串是不可变的,因此在迭代时不能只切换单个字符。您可以使用 abytearray
代替,但是...
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
对象。但是,希望这个想法足够清楚......