在Python解码器中循环遍历字符串中的每个字符

10
我正在尝试使用Python制作一个简单的解码器环。
示例:
a=b, `b=c, c=d, etc.  

我希望脚本能够接收编码信息,并输出解码信息。
例如,我输入"ifmmp",它将输出"hello"

我一直在考虑需要拆分所有字符并循环遍历它们,并更改它们的chr()ord() 值。

Python中似乎没有关于此的文档。


4
您认为缺少哪些文档?for循环、chr()ord()已经有文档。请记住,字符串是不可变的,所以您不能只是将一个字符串更改为另一个字符串,而是必须创建一个新的完全包含新值的字符串。此外,除非这是关于如何执行简单的for循环的作业,否则您可能想完全忘记循环,而直接调用string.translate() - Duncan
4个回答

14

如何尝试:

s = 'ifmmp'
new_s = ''
for c in s:
    n = ord(c)
    n = n - 1
    if n < ord('a'):
        # 'a' -> 'z'
        n = ord('z')
    new_s += chr(n)
# print('new_s = %r' % new_s)  -> new_s = 'hello'

当然,这只处理小写字母,不包括大写字母。


抱歉,但是这个解决方案有一些缺陷。一个小缺陷是函数必须为s中的每个字符c获取ord('a'):替换为数字97会更好。一个更大的缺陷是new_s += chr(n)为s的每个字符创建一个新字符串。如果文本长度为10000,则会看到无用的工作...一个主要的缺陷是大写字母确实被处理了,就像所有具有ord() < 97的字符一样,也就是数字、大写字母、字符!"#$%'()*+,-./:;<=>?@[]^_`和\t \r \n以及其他...更多内容请参见我的答案编辑。 - eyquem
@eyquem 我从不建议使用“魔数”(Magic numbers)作为解决方案。 - Some programmer dude

4

忘记循环,尽可能使用Python内置的功能:

from string import maketrans, translate, ascii_lowercase
import functools
translation = maketrans(ascii_lowercase, ascii_lowercase[-1]+ascii_lowercase[:-1])
decipher = functools.partial(string.translate, table=translation)

print(decipher("ifmmp")) # 'hello'

值得一提的是,在Python 3中,maketransbytesbytearrays的静态函数。详情请参考:https://dev59.com/qXA75IYBdhLWcg3w7tt6 - Wtower

3
from string import maketrans

table = maketrans('abcdefghijklmnopqrstuvwxyz/','zabcdefghijklmnopqrstuvwxy ')

for x in ('pdfbo','qipophsbqi','cmvf/nppo/jo/b/sfe/tlz'):
    print x,' -> ',x.translate(table)

结果

pdfbo  ->  ocean
qipophsbqi  ->  phonograph
cmvf/nppo/jo/b/sfe/tlz  ->  blue moon in a red sky

编辑

我重新编写了Joachim的算法(函数better()),并且我自己写了一个不使用maketrans()的解决方案(yop()):

s = '{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'

def bof(s):
    new_s = ''
    for c in s:
        n = ord(c)
        n = n - 1
        if n < ord('a'):
            # 'a' -> 'z'
            n = ord('z')
        new_s += chr(n)
    return new_s


def better(s):
    li = []
    for c in s:
        n = ord(c)-1
        if n == 96:
            li.append('z')
        elif 96<n<122:
            li.append(chr(n))
        else:
            li.append(c)
    return ''.join(li)

def yop(s):
    gen = ((c,ord(c)-1) for c in s)
    return ''.join('z' if y==96 else chr(y) if 96<y<122 else x for x,y in gen)


def better_yop(s):
    def gen(h):
        for c in h:
            n = ord(c)-1
            if n == 96:
                yield 'z'
            elif 96<n<122:
                yield chr(n)
            else:
                yield c
    return ''.join(gen(s))

for truc in (s,bof(s),better(s),yop(s),better_yop(s)):
    print '%r\n%s\n' % (truc,truc)

结果

'{ifmmp}\t\tcmvf-nppo \n SUNNY ~ ajhabh 14568'
{ifmmp}     cmvf-nppo 
 SUNNY ~ ajhabh 14568

'zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz'
zhello|zzbluezmoonzzzzzzzzz}zzigzagzzzzzz

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

'{hello}\t\tblue-moon \n SUNNY ~ zigzag 14568'
{hello}     blue-moon 
 SUNNY ~ zigzag 14568

然而,我的函数yop()比函数better()慢一些。

.

编辑

现在函数better_yop()的速度等同于函数better()的速度。
然而,better()似乎比better_yop()稍微快一些。由于它也更简单,better()是最好的选择。


1
我建议将解码器环设为字典。然后打开输入文件进行读取,逐个字符循环,并使用字典将其翻译成输出字符串。最后将该字符串写入文件中。

是的,最终我使用了maketrans解决方案,但为所有可能的26个顺序制作了一个翻译表,然后让程序检查输出的英文单词,并将这些英文单词写入文件。 - user1063543

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接