Python Vigenere 元组错误
Posted
技术标签:
【中文标题】Python Vigenere 元组错误【英文标题】:Python Vigenere tuple error 【发布时间】: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
中的字符会发生什么。
【参考方案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
函数并行循环keyList
和plainText
的字符。
我们可以使用%
模数运算符,而不是使用循环来确保键和纯文本索引的总和在适当的范围内。
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.
【讨论】:
以上是关于Python Vigenere 元组错误的主要内容,如果未能解决你的问题,请参考以下文章