4

我正在编写一个 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 以通过字符串递增,然后访问它,但我得到一个运行时错误。我想出的解决方案是在函数的开头创建一个空字符串(从我的谷歌搜索来看,这似乎是大多数人使用的解决方案),但没有人解释为什么会这样。如果要替换其中的每个字符,为什么返回原始字符串不起作用?

4

4 回答 4

4

您的代码中的问题是您没有操作原始字符串。您只是替换临时变量char而不是原始字符串。由于字符串在 python 中是不可变的,您可以尝试使用新字符串,而不是替换原始字符串,您可以将字符附加到新字符串。像:

modified_string = ""
for char in string:
     #whatever condition
     modified_string += #value to be added
于 2013-11-22T17:57:24.893 回答
2

您正在返回原始字符串,请尝试

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)
于 2013-11-22T17:57:56.883 回答
2

Python 中的字符串是不可变的。

于 2013-11-22T18:00:06.437 回答
1

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

于 2013-11-22T18:13:56.027 回答