比堆叠 try 和 except 更好的测试列表中值的方法

Better way to test for a value in a list than to stack try's and except's

我的代码正在实现凯撒密码,这个函数应该将输入的字符串转换为加密的字符串。

为此,我必须在 2 个列表中搜索字符,一个小写字母列表,一个大写字母列表,然后如果不是字母,只需将字符添加到加密字符串中即可。

我决定使用两层 try 和 except 来做到这一点。有没有更好的方法可以做到这一点,也许 if/else?

import string
from tkinter import *
from tkinter import ttk

alphaLower = string.ascii_lowercase
alphaUpper = string.ascii_uppercase
alphaShiftL = alphaLower
alphaShiftU = alphaUpper

def shiftList(amount):
    global alphaShiftL
    global alphaShiftU
    alphaShiftL = alphaLower[amount:] + alphaShiftL[:amount]
    alphaShiftU = alphaUpper[amount:] + alphaShiftU[:amount]

def encrypt(unencrypted):
    encrypted = ''
    for char in unencrypted:
        #HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        try: 
            alphaLower.index(char)
            encrypted += alphaShiftL[alphaLower.index(char)]
        except ValueError:
            try:
                encrypted += alphaShiftU[alphaUpper.index(char)]
            except ValueError:
                encrypted += char

    return encrypted

如果我没理解错的话,你只需要知道列表中是否存在某些内容。您可以使用以下方法测试集合包含:

if search in collection:
    ix = collection.index(search)
else:
    //handle no

我的理解正确吗?

编辑:mgilson 的解决方案,因为您需要元素的索引。

ix = collection.find(search)
if ix != -1:
    //handle yes
else:
    //handle no
if char.islower():
    encrypted += alphaShiftL[alphaLower.index(char)]
elif char.isupper():
    encrypted += alphaShiftU[alphaUpper.index(char)]
else:
    encrypted += char

参见文档 here and here

有更有效的方法来实现这一点——但是使用你所拥有的,我可能建议的第一件事是连接列表,这样你只需要 1 try/except:

alpha = alphaLower + alphaUpper
alphaShift = alphaShiftL + alphaShiftU
for char in unencrypted:
try: 
    encrypted += alphaShift[alpha.index(char)]
except ValueError:
    encrypted += char

现在我们只有一个 try/except 这很好。


如果我们继续只使用包含 映射 的单个对象,我们可以做得更好——更好得多。在这种情况下,您真正​​想要做的是将 alpha 中的一个字符映射到 alphaShift 中的另一个字符。我们可以用 python dict:

简单地做到这一点
mapping = dict(zip(alpha, alphaShift))
for char in unencrypted:
    encrypted += mapping.get(char, char)

或者,更有效:

mapping = dict(zip(alpha, alphaShift))
encrypted = ''.join(mapping.get(char, char) for char in unencrypted)

到"decrypt",你只需要逆映射:

inverse_mapping = dict(zip(alphaShift, alpha))
unencrypted = ''.join(inverse_mapping.get(char, char) for char in encrypted)

除非这是一个学术练习,否则我不明白你为什么要这样组织你的代码。如果您热衷于将信息保存在数组中,那么您可以将它们连接在一起,这样您只需一次查找即可。

alphaLower = string.ascii_lowercase
alphaUpper = string.ascii_uppercase
alpha = alphaLower + alphaUpper
alphaShift = alpha

def shiftList(amount):
    global alphaShiftL
    global alphaShiftU
    alphaShiftL = alphaLower[amount:] + alphaShiftL[:amount]
    alphaShiftU = alphaUpper[amount:] + alphaShiftU[:amount]
    alphaShift = alphaShiftL + alphaShiftU

现在您可以直接进行查找:

def encrypt(unencrypted):
    encrypted = ''
    for char in unencrypted:
        idx = alpha.find(char)
        encrypted += alphaShift[idx] if idx >= 0 else char
    return encrypted

但是,只使用字典会好得多:

lc = string.ascii_lowercase
uc = string.ascii_uppercase

cipher = dict(zip(lc+uc, lc[13:]+lc[:13]+uc[13:]+uc[:13]))

def encrypt(input):
    return ''.join(cipher.get(c,c) for c in input)