繁体   English   中英

Python Vigenere工作正常,但是我无法使用函数说明空格和非字母字符

[英]Python Vigenere working, but I can't account for the spaces and non alphabetical characters using functions

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

然而,事实证明,困难得多。 实际上,我能够找到一段代码,如果仅使用字母字符,但是只要输入任何非字母字符(例如!或?),就可以使用第一个函数(alphabet_position)进行修改以使工作正常我得到ValueError的返回:找不到子字符串。 当程序遇到这些非字母字符时,该键应跳过它们并将键的第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()

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

现在,执行此操作的次佳方法是if ... in ...使用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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM