用 Python 简化 Vigenere 密码程序

Posted

技术标签:

【中文标题】用 Python 简化 Vigenere 密码程序【英文标题】:Simplifying Vigenere cipher program in Python 【发布时间】:2016-05-12 20:16:12 【问题描述】:

我有下面的程序,它被传递给另一个函数,该函数简单地打印出原始和加密的消息。我想知道如何简化这个程序,特别是“match = zip”和“change = (reduce(lambda”) 行。如果可以在不使用 lambda 的情况下做到这一点,我该怎么做?

from itertools import cycle

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

def vigenereencrypt(message,keyword):
    output = ""    
    match = zip(message.lower(),cycle(keyword.lower()))
    for i in match:
        change = (reduce(lambda x, y: alphabet.index(x) + alphabet.index(y), i)) % 26
        output = output + alphabet[change]
    return output.lower()

【问题讨论】:

【参考方案1】:

两件事:

    你不需要有一个局部变量match,只需循环zip 您可以在 for 循环定义中拆分两个索引 xy,而不是使用 reduce; reduce 通常用于较大的可迭代对象,由于 i 中只有 2 个项目,因此会增加不必要的复杂性。

即,您可以将 for 循环定义更改为:

for x, y in zip(...):

以及您对change 的定义:

change = (alphabet.index(x) + alphabet.index(y)) % 26

【讨论】:

【参考方案2】:

从R Nar所说的开始:

def vigenereencrypt(message,keyword):
    output = ""
    for x, y in zip(message.lower(), cycle(keyword.lower())):
        change = (alphabet.index(x) + alphabet.index(y)) % 26
        output = output + alphabet[change]
    return output.lower()

我们可以通过使用列表然后加入它来提高效率,而不是添加到字符串中,并且还可以通过注意输出已经是小写:

def vigenereencrypt(message,keyword):
    output = []
    for x, y in zip(message.lower(), cycle(keyword.lower())):
        change = (alphabet.index(x) + alphabet.index(y)) % 26
        output.append(alphabet[change])
    return "".join(output)

然后我们可以将循环体减少到一行..

def vigenereencrypt(message,keyword):
    output = []
    for x, y in zip(message.lower(), cycle(keyword.lower())):
        output.append(alphabet[(alphabet.index(x) + alphabet.index(y)) % 26])
    return "".join(output)

...所以我们可以把它变成一个列表推导:

def vigenereencrypt(message,keyword):
    output = (
        alphabet[(alphabet.index(x) + alphabet.index(y)) % 26]
        for x, y in zip(message.lower(), cycle(keyword.lower()))
    )
    return "".join(output)

我觉得我们可以用 map(alphabet.index, ...) 做一些事情,但我想不出比列表理解更好的方法。

【讨论】:

【参考方案3】:

你可以用一堆索引而不是 zip 来做到这一点......

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
alphaSort = k:n for n,k in enumerate(alphabet)
alphaDex = n:k for n,k in enumerate(alphabet)

def vigenereencrypt(message,keyword):
    output = ""    
    #match = zip(message.lower(),cycle(keyword.lower()))      # zip(a,cycle(b)) Creates [(a[n],b[n%len(b)]) for k in range(len(a)) ] 
    op = ""                                                  # So lets start with  for k in range(len(a))
    for k in range(len(message)):
        op += alphaDex[(alphaSort[message.lower()[k]]+alphaSort[keyword.lower()[k%len(keyword)]])%len(alphabet)]
    return(op)

【讨论】:

以上是关于用 Python 简化 Vigenere 密码程序的主要内容,如果未能解决你的问题,请参考以下文章

python 用Python实现的Vigenere密码。

cs50 的 Vigenere 密码程序错误

Python:解码使用仿射密码编码的 Vigenere 密码

python中的Vigenere密码[关闭]

Python中的Vigenere密码不适用于大写/小写字母转换

vigenere密码中的itertools循环导致空间问题python