Python3 - 索引超出范围(Vigenere Cipher)

时间:2016-02-03 18:53:25

标签: python loops vigenere

我开始制作代码来执行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

1 个答案:

答案 0 :(得分:2)

您的代码无法运作的原因:

del key[-difference]

应该是:

del finalkey[-difference]

删除该元素后,您在IndexError行(其中i = 3)中尝试访问key[3]时会遇到finalkey.append(key[i])

只是为了好玩,这是一个替代实现。

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功能允许我们采取&#34;切片&#34;迭代器对象。在Python中,&#34;切片&#34;是表达式[0:3]的{​​{1}}部分的术语 - 我们&#34;切片&#34;出一个原始的子集。由于我们不希望我们的字符串无限长 - 这不会非常有用 - 我们只想获取我们创建的new = old[0:3]的一部分:

cycle

这需要我们的迭代器 - islice(cycle(key), len(message) - 并从索引0开始并以索引cycle(key)结束。这将返回另一个迭代器 - 这次,它不是无限的。迭代器的内容现在是:len(message)

现在,我们只需要将"L", "O", "V", "E", "L", "O"拼接成整个字符串:

islice

只是为了在工具箱中提供另一个工具!