Python Vigenere工作,但我不能使用函数来解释空格和非字母字符

时间:2017-06-21 01:20:19

标签: python encryption alphabet vigenere

我目前正在为初学者python课程开发一个密码程序。我们首先被告知创建一个函数,它将返回给定字母的位置,使用字母表的字符串作为参考(这是我的alphabet_position函数。)接下来,我们被告知要创建一个允许单个函数的函数要按所选数字旋转的字母(即我的rotate_character函数)。第三,我们的任务是使用前两个函数创建一个基本的凯撒密码。所有这些我都能够通过下面的代码证明这一点。

然而,vigenere证明要困难得多。我实际上能够找到一个代码片段,我可以用我的第一个函数(alphabet_position)修改,如果只使用字母字符就可以工作,但只要我输入任何非字母字符(例如!或?)我得到ValueError的返回:未找到子字符串。当程序遇到这些非字母字符时,键应该跳过它们并将键的第N个字符带到下一个字母字符。

我猜测的答案在于以某种方式将我的rotate_character函数合并到我的加密函数中,但我不确定如何做到这一点,因为rotate_character函数需要一个字母字符,而vigenere函数在运行之前将该参数转换为int它通过。

有什么建议吗?由于我是一名新的程序员,我很乐意对你可能想要灌输的编码实践提出任何其他有用的批评!“

> #Create function alphabet_position(letter) to turn letter into number
> #such as a=0 or e=4, using lowercase to make sure case doesnt matter. 
  alphabet = "abcdefghijklmnopqrstuvwxyz" 
  def alphabet_position(letter):
>     lower_letter = letter.lower()   #Makes any input lowercase.
>     return alphabet.index(lower_letter) #Returns the position of input 
                                           as a number.
> 
> def rotate_character(char, rot):
>     if char.isalpha():
>         a = alphabet_position(char);
>         a = (a + rot) % (int(len(alphabet)));            #needs modulo
>         a = (alphabet[a]);
>         if char.isupper():
>             a = a.title()
>         return a
>     else:
>        return char
> 
> def caesar(text, rot):
>     list1 = ""
>     for char in text:
>         list1 += rotate_character(char, rot)
>     return list1
> 
> def vigenere(text,key):       
    m = len(key)
> 
>   newList = ""
> 
>   for i in range(len(text)):      
        text_position = alphabet_position(text[i])      
        key_position =  alphabet_position(key[i % m])       
        value = (text_position + key_position) % 26         
        newList += alphabet[value]      
    return newList
> 
> def main():
>     x = input("Type a message: ")
>     y = input("Rotate by: ")
>     result = vigenere(x, y)
>     print (result)
> 
> if __name__ == '__main__':   
      main()

1 个答案:

答案 0 :(得分:1)

不,你不再需要旋转功能了。您只需要将不在字母表中的任何字符直接添加到新列表中,然后跳过加密部分。

现在,执行此操作的次优方法是使用if ... in ...

if text[i] in alphabet:
    # do your thing
else:
    newList += text[i]

当然更优化的是只使用一次字母并使用变量:

pt_c = text[i]
pt_i = alphabet.find(pt_c) # returns -1 instead of an error when not found
if pt_i == -1:
    newList += pt_c
else:
    newList += pt_c
    # do your thing *with the given index*

当然,这对Vigenère密码的运行时没有任何影响。但它告诉你如何考虑以后的高效编程:没有必要搜索两次。

您也可以continue循环而不是使用else语句:

pt_c = text[i]
pt_i = alphabet.find(pt_c) # returns -1 instead of an error when not found
if pt_i == -1:
    continue
# do your thing with the given index

这将使循环的缩进深度(范围的数量)减少,使得循环更复杂(创建本地出口点)的不幸副作用。