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

Posted

技术标签:

【中文标题】Python Vigenere 工作,但我无法使用函数来解释空格和非字母字符【英文标题】:Python Vigenere working, but I can't account for the spaces and non alphabetical characters using functions 【发布时间】:2017-06-21 01:20:18 【问题描述】:

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

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

我猜答案在于以某种方式将我的 rotate_character 函数合并到我的 Encrypt 函数中,但我不确定如何执行此操作,因为 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】:

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

现在这样做的次优方法是使用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

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

【讨论】:

我尝试了您提供的第一个选项,效果很好!我会和其他人混在一起,看看他们是如何工作的。有兴趣尝试学习,你有没有看到我可以调整我的 rotate_character 函数以在我的 vigenere 函数中使用它?如果没有,那很好。非常感谢您的帮助! 当然,再看看for 循环和rotate_character 函数中的for 4 语句。他们看起来是不是有点眼熟?如果您将key_position 用作rot 参数会怎样? 谢谢!我将开始对所有这些进行试验,看看它们在我的脚本中是如何工作的!

以上是关于Python Vigenere 工作,但我无法使用函数来解释空格和非字母字符的主要内容,如果未能解决你的问题,请参考以下文章

加密大写字母 python vigenere

python中的Vigenere密码[关闭]

Vigenere-cipher 错误输出

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

具有所需功能的 Python Vigenere Cipher

C++ 链表凯撒密码 Vigenere Cipher