【问题标题】:Python Vigenere tuple errorPython Vigenere 元组错误
【发布时间】:2017-03-17 12:49:32
【问题描述】:

我正在尝试制作 Vigenere 密码。当我尝试加密消息时,出现以下错误。

    cipherCharIndexValue = baseAlphabet.index(keyList[keyIncrement]) + baseAlphabet.index(plainTextChar)
ValueError: tuple.index(x): x not in tuple

我不确定是什么问题导致了错误,有什么帮助吗?

baseAlphabet = ('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')

plainText = input("Please enter the plain text")
key = input("Please enter the key word")
keyList = []
keyLength = 0
while keyLength < len(plainText):
    #Adds the users entered key into a list character by character. 
    #Also makes the key the same length as plainText
    for char in key:
        if keyLength < len(plainText):
            keyList.append(str(char))
            keyLength = keyLength + 1

#The variable each processed letter is appended to
completeCipherText = [] 
#This is the value used to temporaily store the ciphertext character during the iteration
cipherCharIndexValue = 0
keyIncrement = 0

#iterates through the plain text
for plainTextChar in plainText:
        #Adds the base alphabets index value of the key and the plain text char
        cipherCharIndexValue = baseAlphabet.index(keyList[keyIncrement]) + baseAlphabet.index(plainTextChar)
        while cipherCharIndexValue > 25:
             #makes the addition value under 26 as to not go out of range of base alphabet tuple
            cipherCharIndexValue = cipherCharIndexValue - 26 
         #appends the ciphertext character to the completeCipherText variable. 
         #The character is the index of the key + index of the       plainTextChar from baseAlphabet
        completeCipherText.append(baseAlphabet[cipherCharIndexValue])
         #Moves onto the next key
        keyIncrement = keyIncrement + 1
print ('').join(completeCipherText)#Makes the result a strings for printing to the console.

【问题讨论】:

  • 我尝试运行您的代码并在第 2 行得到一个 IndentationError。在取消缩进包括第一个 while 循环的所有内容后,我在第 28 行得到一个 IndentationError。在取消缩进该行之后一个空格,我得到了NameError: name 'baseAlphabet' is not defined。请发一个minimal reproducible example 来证明你的问题。
  • keyList[keyIncrement]plainTextChar 不在 baseAlphabet 中。您需要进行一些故障排除才能确定究竟是哪个值失败了。
  • 感谢您编辑代码。它现在为我运行。当我使用 Python 2 执行它,并为第一个提示输入 "foo" 并为第二个提示输入 "bar" 时,它运行时不会崩溃并输出 gof。请描述您输入的哪些输入导致程序崩溃。
  • 考虑如果plainText(或keyList)包含一个不在baseAlphabet中的字符会发生什么。

标签: python vigenere


【解决方案1】:

看来你使用的是python2.x,你应该使用raw_input而不是input

如果输入字符串中有空格或其他标点符号,你的代码会崩溃,所以我建议你在使用index方法之前确保keyList[keyIncrement]baseAlphabet中,如果它不在这个元组中,你会得到这个错误:

ValueError: tuple.index(x): x not in tuple

例如

if keyList[keyIncrement] in keyList:
    cipherCharIndexValue = baseAlphabet.index(keyList[keyIncrement]) + baseAlphabet.index(plainTextChar)

或者您可以使用try/catch 捕获异常以调试您的代码。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    每当您尝试获取不在baseAlphabet 中的字符的索引时,您都会收到ValueError: tuple.index(x): x not in tuple 错误。所以你需要确保key 只包含这样的字符,并且在编码plainText 时要么避免编码“坏”字符,而是将它们原封不动地复制到completeCipherText 列表中,或者将它们转换为有效的baseAlphabet 字符.

    在传统加密中,将所有空格和标点符号转换为另一个字符是很常见的,例如'x''.'。我决定将'.' 添加到baseAlphabet 并编写一个小函数fix_string 来执行该操作。 fix_string 还确保所有字母都是小写的。

    我还对您的代码做了一些其他小的简化。

    baseAlphabet 没有必要成为一个元组。我们可以使用字符串。但是如果您确实想使用单个字符的元组,则无需完整地写出来,您只需将字符串传递给tuple 构造函数,例如

    tuple("some string")
    

    我们通常不需要跟踪列表、字符串等集合的长度。所有内置集合都跟踪自己的长度,我们可以使用len() 函数有效地访问该长度。

    我们不需要keyIncrement。相反,我们可以使用zip 函数并行循环keyListplainText 的字符。

    我们可以使用% 模数运算符,而不是使用循环来确保键和纯文本索引的总和在适当的范围内。

    from __future__ import print_function
    
    baseAlphabet = 'abcdefghijklmnopqrstuvwxyz.'
    
    # Process s so that it only contains chars in baseAlphabet
    def fix_string(s):
        # Convert to lower case
        s = s.lower()
        # Convert "other" chars to dot
        a = [ch if ch in baseAlphabet else '.' for ch in s]
        return ''.join(a)
    
    # Vignere cipher
    # mode = 1 to encode, -1 to decode
    def vignere(plainText, key, mode):
        keyList = []
        while len(keyList) < len(plainText):
            # Adds the key into a list character by character. 
            # Also makes the key the same length as plainText
            for char in key:
                if len(keyList) < len(plainText):
                    keyList.append(str(char))
    
        # The variable each processed letter is appended to
        completeCipherText = []
    
        # iterates through the plain text
        for keyChar, plainTextChar in zip(keyList, plainText):
            # Adds the base alphabet's index value of the plain text char and the key char
            cipherCharIndexValue = baseAlphabet.index(plainTextChar) 
            cipherCharIndexValue += mode * baseAlphabet.index(keyChar)
            # makes the addition value in range(len(baseAlphabet))
            cipherCharIndexValue = cipherCharIndexValue % len(baseAlphabet)
    
            # appends the ciphertext character to the completeCipherText variable. 
            # The character is the index of the key + index of the plainTextChar from baseAlphabet
            completeCipherText.append(baseAlphabet[cipherCharIndexValue])
    
        # Makes the result a string
        return ''.join(completeCipherText)
    
    # Test
    
    # plainText = raw_input("Please enter the plain text")
    # key = raw_input("Please enter the key word")
    
    plainText = 'This, is a test string!'
    key = 'the key'
    
    # Process plainText and key so that they only contain chars in baseAlphabet
    plainText = fix_string(plainText)
    key = fix_string(key)
    
    ciphertext = vignere(plainText, key, 1)
    print(ciphertext)
    
    decoded = vignere(ciphertext, key, -1)
    print(decoded)
    

    输出

    lomrjdfkgezciplgwsamkzg
    this..is.a.test.string.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      相关资源
      最近更新 更多