Python3 - 索引超出范围(Vigenere 密码)
Python3 - index out of range (Vigenere Cipher)
我开始编写代码来执行 Vigenere 密码加密。首先,我想制作钥匙。密钥需要一遍又一遍地重复,直到它与要加密的消息的长度相匹配,所以我创建了一个函数来为我做这件事:
def makekey(key, message):
finalkey = []
print(message) # to see if the key fits under the message correctly
key = list(key)
while len(finalkey) < len(message): # while the key is shorter than the message
for i in range(0, len(key)): # iterate through characters in the key
finalkey.append(key[i]) # append the characters in the processed key list
if len(finalkey) > len(message): # if the final key is still bigger than the message
difference = len(finalkey) - len(message) # finds the difference between the two
del key[-difference] # removes the difference
return ''.join(finalkey) # joins the final key into a string
print(makekey("LOVE", "Python")) # calling the function
输出应如下所示:
Python
LOVELO
但是程序只是给我一个索引超出范围的错误,我不知道发生了什么!
错误信息:
Traceback (most recent call last):
File "test.py", line 14, in <module>
print(makekey("LOVE", "Python")) # calling the function
File "test.py", line 8, in makekey
finalkey.append(key[i]) # append the characters in the processed key list
IndexError: list index out of range
您的代码不起作用的原因:
del key[-difference]
应该是:
del finalkey[-difference]
您在删除该元素后尝试访问 finalkey.append(key[i])
行(其中 i=3)中的 key[3]
得到一个 IndexError
。
为了好玩,这里有一个替代实现。
def make_key(key, message):
""" Returns a string that repeats the `key` string until it's
the length of the `message` string
"""
if len(key) < len(message): # only lengthen key if it's too short
# In python, "abc" * 3 == "abcabcabc"
# so what would we need to multiply our `key` by to get
# it to be as long as `message`, or longer?
# A guaranteed answer is: floor(len(message) / len(key)) + 1
multiplier = (len(message) // len(key)) + 1
key = key * multiplier
# now we have a `key` that is at least as long as `message`
# so return a slice of the key where the end of the slice == len(message)
return key[:len(message)]
print(makekey("LOVE", "Python"))
打印:LOVELO
编辑 - 神秘的单行解决方案
如果你想让所有阅读你代码的人都对你翻白眼,你可以试试这个:
from itertools import islice, cycle
key = "LOVE"
message = "Python"
finalkey = ''.join(islice(cycle(key), len(message)))
cycle
函数接受一个 iterable
对象——在我们的例子中是 key
字符串——并在无限循环中重复它。所以,如果我们创建 cycle("LOVE")
它将永远生成 "L", "O", "V", "E", "L", "O", "V", "E", "L" ...
。
islice
函数允许我们获取迭代器对象的 "slice"。在 Python 中,"slice" 是表达式 new = old[0:3]
的 [0:3]
部分的术语 - 我们 "sliced" 出原始的子集。由于我们不希望我们的字符串无限长 - 这不会很有用 - 我们只想获取我们创建的 cycle
的一部分:
islice(cycle(key), len(message)
这需要我们的迭代器 - cycle(key)
- 并将其从索引 0 开始切片并在索引 len(message)
结束。这将 return 另一个迭代器——这次不是无限迭代器。迭代器的内容现在是:"L", "O", "V", "E", "L", "O"
.
现在,我们只需要将 islice
拼接成一个完整的字符串:
''.join(islice...) == "LOVELO"
只是为了给你工具箱中的另一个工具!
我开始编写代码来执行 Vigenere 密码加密。首先,我想制作钥匙。密钥需要一遍又一遍地重复,直到它与要加密的消息的长度相匹配,所以我创建了一个函数来为我做这件事:
def makekey(key, message):
finalkey = []
print(message) # to see if the key fits under the message correctly
key = list(key)
while len(finalkey) < len(message): # while the key is shorter than the message
for i in range(0, len(key)): # iterate through characters in the key
finalkey.append(key[i]) # append the characters in the processed key list
if len(finalkey) > len(message): # if the final key is still bigger than the message
difference = len(finalkey) - len(message) # finds the difference between the two
del key[-difference] # removes the difference
return ''.join(finalkey) # joins the final key into a string
print(makekey("LOVE", "Python")) # calling the function
输出应如下所示:
Python
LOVELO
但是程序只是给我一个索引超出范围的错误,我不知道发生了什么!
错误信息:
Traceback (most recent call last):
File "test.py", line 14, in <module>
print(makekey("LOVE", "Python")) # calling the function
File "test.py", line 8, in makekey
finalkey.append(key[i]) # append the characters in the processed key list
IndexError: list index out of range
您的代码不起作用的原因:
del key[-difference]
应该是:
del finalkey[-difference]
您在删除该元素后尝试访问 finalkey.append(key[i])
行(其中 i=3)中的 key[3]
得到一个 IndexError
。
为了好玩,这里有一个替代实现。
def make_key(key, message):
""" Returns a string that repeats the `key` string until it's
the length of the `message` string
"""
if len(key) < len(message): # only lengthen key if it's too short
# In python, "abc" * 3 == "abcabcabc"
# so what would we need to multiply our `key` by to get
# it to be as long as `message`, or longer?
# A guaranteed answer is: floor(len(message) / len(key)) + 1
multiplier = (len(message) // len(key)) + 1
key = key * multiplier
# now we have a `key` that is at least as long as `message`
# so return a slice of the key where the end of the slice == len(message)
return key[:len(message)]
print(makekey("LOVE", "Python"))
打印:LOVELO
编辑 - 神秘的单行解决方案
如果你想让所有阅读你代码的人都对你翻白眼,你可以试试这个:
from itertools import islice, cycle
key = "LOVE"
message = "Python"
finalkey = ''.join(islice(cycle(key), len(message)))
cycle
函数接受一个 iterable
对象——在我们的例子中是 key
字符串——并在无限循环中重复它。所以,如果我们创建 cycle("LOVE")
它将永远生成 "L", "O", "V", "E", "L", "O", "V", "E", "L" ...
。
islice
函数允许我们获取迭代器对象的 "slice"。在 Python 中,"slice" 是表达式 new = old[0:3]
的 [0:3]
部分的术语 - 我们 "sliced" 出原始的子集。由于我们不希望我们的字符串无限长 - 这不会很有用 - 我们只想获取我们创建的 cycle
的一部分:
islice(cycle(key), len(message)
这需要我们的迭代器 - cycle(key)
- 并将其从索引 0 开始切片并在索引 len(message)
结束。这将 return 另一个迭代器——这次不是无限迭代器。迭代器的内容现在是:"L", "O", "V", "E", "L", "O"
.
现在,我们只需要将 islice
拼接成一个完整的字符串:
''.join(islice...) == "LOVELO"
只是为了给你工具箱中的另一个工具!