Python中的移位密码:使用ord时出错

3 投票
4 回答
3108 浏览
提问于 2025-04-17 11:12

我想把一个字符串里的每个字符都换成字母表中往后移动的另一个字符。在下面的例子中,我是往后移动2个位置,所以a变成c,b变成d,依此类推。

我想用正则表达式和sub函数来实现这个功能,但我遇到了一个错误。

这是我写的代码:

p = re.compile(r'(\w)')
test = p.sub(chr(ord('\\1') + 2), text)
print test

这里的变量text是输入的字符串。

然后我收到了这个错误:

TypeError: ord() 期望一个字符,但找到了长度为2的字符串

我觉得问题出在ord函数被调用在了字面字符串"\1"上,而不是正则表达式匹配到的\w字符上。那我该怎么做才对呢?

4 个回答

1

试试这个,用列表推导式:

input = 'ABC'
''.join(chr(ord(c)+2) for c in input)
> 'CDE'

这样比用正则表达式简单多了。

2

完整版本

def shouldShift(char):
    return char in string.lowercase

def caesarShift(string, n):
    def letterToNum(char):
        return ord(char)-ord('a')
    def numToLetter(num):
        return chr(num+ord('a'))

    def shiftByN(char):
        return numToLetter((letterToNum(char)+n) % 26)

    return ''.join((shiftByN(c) if shouldShift(c) else c) for c in string.lower())

一句话解决方案

如果你真的想要一句话的解决方案,那就是这个,不过我觉得这个写得不太好看:

''.join(chr((ord(c)-ord('a')+n)%26 + ord('a')) for c in string)

演示

>>> caesarShift(string.lowercase, 3)
'defghijklmnopqrstuvwxyzabc'
4

这样是行不通的。Python 首先会计算 chr(ord('\\') + 2 的结果,然后把这个结果传给 p.sub

你需要把它放在一个单独的函数里,或者使用一个匿名函数(也叫 lambda 函数):

p = re.compile(r'(\w)')
test = p.sub(lambda m: chr(ord(m.group(1)) + 2), text)
print test

更好的方法是使用 maketrans,而不是正则表达式:

import string

shift = 2

t = string.maketrans(string.ascii_lowercase, string.ascii_lowercase[shift:] +
                                             string.ascii_lowercase[:shift])
string.translate(text, t)

撰写回答