你在这里做的事情有很多问题。你在don't do that的捆绑包中混合了递归、迭代和异常。
我想你可能对做什么有一些想法,你从一条轨道开始,然后改变到另一条轨道。这并不奇怪,因为您是初学者。但是你应该知道保持一致是个好主意。您可以使用递归、迭代、切片或异常驱动来做到这一点。但是在不理解为什么要这样做的情况下将它们全部组合起来是一个问题。
设计
让我们将您的应用程序展开为您真正想要做的事情。如果不编写任何代码,您将如何描述您正在采取的步骤?这就是我要说的:
对于消息中的每个字母:
- 从关键字中取出下一个字母
- 结合两个字母的数值
- 如果字母超出 Z(ebra),则从 A 开始并继续计数
- 当我们到达关键字中的最后一个字母时,循环回到开头
这给了我们一个关于如何编写这个的提示。确实是最直接的方法,而且您已经完成了部分工作。
迭代地
这是另一个指针 - 与其从动态问题开始,不如让它变得相当静态:
message = 'computing is awesome'
for letter in message:
print(letter)
您会看到这会打印出消息 - 每行一个字符。伟大的!我们已经完成了问题的第一部分。现在下一步是从密钥中获取字母。好吧,让我们把钥匙放在那里。但是我们如何一次迭代两个字符串呢?如果我们在 google 上搜索python iterate over two sequences
,对我来说第一个结果是如何并行遍历两个列表?. 不错。它告诉我们方便的花花公子zip
功能。如果你想了解它,你可以搜索python3 zip
或>>> help(zip)
在你的 REPL 中运行。
所以这是我们的代码:
message = 'computing is awesome'
keyword = 'gcse'
for letter, key in zip(message, keyword):
print(letter, key)
现在,如果我们运行这个......呃哦!
c g
o c
m s
p e
我们剩下的字符串在哪里?它在我们到达最短字符串的末尾后停止。如果我们查看 zip 的帮助,我们会看到:
一直持续到参数序列中最短的可迭代项用完
所以它只会持续到最短的时间。好吧,那真是太可惜了。这意味着我们需要拥有相同长度的密钥和消息,对吗?或者是吗?如果我们的密钥比消息长怎么办?希望现在你知道你可以做这样的事情:
>>> 'ab'*10
'abababababababababab'
如果我们确保我们的密钥至少和我们的消息一样长,那将起作用。因此,我们可以将密钥乘以消息中的字母数。我的意思是,我们将拥有比我们需要的更多的东西,但这应该有效,对吧?让我们试一试:
message = 'computing is awesome'
keyword = 'gcse'*len(message)
for letter, key in zip(message, keyword):
print(letter, key)
甜的!有效!
所以现在让我们尝试添加这些ord
值,让我们看看我们得到了什么:
for letter, key in zip(message, keyword):
print(chr(ord(letter)+ord(key)))
哦亲爱的。好吧,那些不是 ASCII 字母。正如您已经发现的那样,您需要从每个中减去 96。事实证明,因为数学,你实际上可以从我们已经得到的总和中减去 96*2。
for letter, key in zip(message, keyword):
if letter == ' ':
print()
else:
new_code = (ord(letter)+ord(key)-96*2)
print(chr(new_code+96))
但是我们这里仍然有非字母字符。因此,如果我们确保将这个价值带回来:
for letter, key in zip(message, keyword):
if letter == ' ':
print()
else:
new_code = (ord(letter)+ord(key)-96*2)
if new_code > 26:
new_code -= 26
print(chr(new_code+96))
现在我们很好。我们唯一要做的就是将我们的消息组合成一个字符串而不是打印出来,然后将这段代码粘贴到一个函数中。然后从用户那里得到我们的输入。我们还将把增加密钥长度的代码粘贴到函数中:
def change(message, keyword):
if len(keyword) < len(message):
keyword = keyword * len(message)
result = ''
for letter, key in zip(message, keyword):
if letter == ' ':
result += ' '
else:
new_code = (ord(letter)+ord(key)-96*2)
if new_code > 26:
new_code -= 26
result += chr(new_code+96)
return result
message = input('enter your sentence: ')
keyword = input('enter your keyword: ')
print(change(message, keyword))
递归
所以我们已经使用迭代让它工作了。递归呢?您肯定在解决方案中使用了递归。好吧,让我们回到开头,弄清楚如何逐字打印我们的信息:
message = 'computing is awesome'
def change(message):
if not message:
return
print(message[0])
change(message[1:])
change(message)
这样可行。现在我们要添加我们的密钥。事实证明,我们实际上可以做与以前相同的事情——只需将其相乘:
def change(message, keyword):
if not message:
return
if len(keyword) < len(message):
keyword = keyword*len(message)
print(message[0], keyword[0])
change(message[1:], keyword[1:])
嗯,这非常简单。现在让我们打印出转换后的值:
def change(message, keyword):
if not message:
return
if len(keyword) < len(message):
keyword = keyword*len(message)
new_code = (ord(message[0])+ord(keyword[0])-96*2)
if new_code > 26:
new_code -= 26
print(chr(new_code+96))
change(message[1:], keyword[1:])
我们再次需要处理一个空格字符:
def change(message, keyword):
if not message:
return
if len(keyword) < len(message):
keyword = keyword*len(message)
if message[0] == ' ':
print()
else:
new_code = (ord(message[0])+ord(keyword[0])-96*2)
if new_code > 26:
new_code -= 26
print(chr(new_code+96))
change(message[1:], keyword[1:])
现在唯一剩下的就是合并结果。在递归中,您通常会传递某种值,我们将使用我们的结果来做到这一点:
def change(message, keyword, result=''):
if not message:
return result
if len(keyword) < len(message):
keyword = keyword*len(message)
if message[0] == ' ':
result += ' '
else:
new_code = (ord(message[0])+ord(keyword[0])-96*2)
if new_code > 26:
new_code -= 26
result += chr(new_code+96)
return change(message[1:], keyword[1:], result)
print(change(message, keyword))
切片
我们在递归方法中使用了一些切片。我们甚至可以传入索引,而不是切掉部分字符串。但现在我们要切片和切块。这将与我们的递归解决方案非常相似:
def 更改(消息,关键字):如果 len(关键字)< len(消息):关键字 = 关键字 * len(消息)
while message:
print(message[0], keyword[0])
message = message[1:]
keyword = keyword[1:]
当您看到这一点时,不难意识到您可以从我们的递归解决方案中放入代码:
while message:
if message[0] == ' ':
print()
else:
new_code = (ord(message[0])+ord(keyword[0])-96*2)
if new_code > 26:
new_code -= 26
print(chr(new_code+96))
message = message[1:]
keyword = keyword[1:]
然后我们只是将字符组合成结果:
def change(message, keyword):
if len(keyword) < len(message):
keyword = keyword*len(message)
result = ''
while message:
if message[0] == ' ':
result += ' '
else:
new_code = (ord(message[0])+ord(keyword[0])-96*2)
if new_code > 26:
new_code -= 26
result += chr(new_code+96)
message = message[1:]
keyword = keyword[1:]
return result
延伸阅读
你可以做一些更好的事情。而不是我们用密钥做的愚蠢的乘法,那么itertools.cycle怎么样?
当您使用模除法而不是减法时会发生什么?