如何提高Python代码的效率

时间:2017-09-07 18:08:31

标签: python caesar-cipher

我非常感谢您对我的第一个Python项目的反馈! :d

基本上我正在编写一个Caesar Cipher,如果你知道我的意思,我认为它非常“优化/高效”,这是因为我复制并粘贴了encrypt()方法的encrypt()方法,这是唯一的事情。我改变了而不是更多地旋转数字,我把它们旋转得更少。这就是我所说的:

       newPosition = (abc.find(letter) - key) % 26

^^ Instead of having a + (plus) I made it a - (minus) ^^

有没有办法可以在newPosition行调用encrypt()方法?或者我所做的是正确的,它不需要修复(我非常怀疑)

**请记住,我从今天开始就没有太多的Python知识(如果有的话),所以不要用一些超级复杂的代码来吹嘘我的大脑。谢谢!!! **

abc = 'abcdefghijklmnopqrstuvwxyz'

def main():
    message = input("Would you like to encrypt or decrypt a word?")
    if message.lower() == "encrypt":
        encrypt()
    elif message.lower() == "decrypt":
        decrypt()
    else:
        print("You must enter either 'encrypt' or 'decrypt'.")
        main()


def encrypt():
    message = input("Enter a message to encrypt: ")
    message = message.lower()
    key = int(input("What number would you like for your key value?"))
    cipherText = ""
    for letter in message:
        if letter in abc:
            newPosition = (abc.find(letter) + key) % 26
            cipherText += abc[newPosition]
        else:
            cipherText += letter
    print(cipherText)
    return cipherText

def decrypt():
    message = input("Enter a message to decrypt: ")
    message = message.lower()
    key = int(input("What number would you like for your key value?"))
    cipherText = ""
    for letter in message:
        if letter in abc:
            newPosition = (abc.find(letter) - key) % 26
            cipherText += abc[newPosition]
        else:
            cipherText += letter
    print(cipherText)
    return cipherText

main()

1 个答案:

答案 0 :(得分:3)

一般来说,str.find在性能方面表现不佳。它的O(n)复杂性并不可怕,但你很少需要它。在这种情况下,您可以使用ord将每个字母转换为其序数,然后减去ord('a')以获得0-25而不是97-122。

这特别有用,因为您可以使用chr转换回而无需查找。

for letter in message:
    if letter in string.ascii_lowercase:  # same as "abcdef..z"
        new_position = ((ord(letter) - ord('a') + key) % 26) + ord('a')
        new_ch = chr(new_position)
        ciphertext += new_ch

另请注意,使用+=连接字符串的速度不会像str.join那样快。

new_letters = [chr(((ord(letter) - ord('a') + key) % 26) + ord('a')) if letter in ascii_lowercase else letter for letter in message]
ciphertext = "".join(new_letters)

由于chr(((ord(letter) - ord('a') + key) % 26) + ord('a'))非常难看,我将其重构为一个函数。

def rotate(letter, key=0):
    c_pos = ord(letter) - ord('a')
    rotated = c_pos + key
    modded = rotated % 26
    final_pos = modded + ord('a')
    return chr(final_pos)

new_letters = [rotate(c, key) if c in string.ascii_lowercase else c for c in letters]
ciphertext = "".join(new_letters)

可维护性:如果您将输入与结果分开,则可以更轻松地编写可测试的优秀代码。现在,您必须对stdin进行一些猴子修补,为您的任何功能编写单元测试,但是如果您将用户输入的请求移到main并且从他们各自的功能中移出,这变得容易多了。

def main():
    message = input("What's the message to encrypt/decrypt? ")
    key = int(input("What number would you like for your key value? "))
    choice = input("Choose: encrypt or decrypt. ")
    if choice == "encrypt":
        result = encrypt(message, key)
    elif choice == "decrypt":
        result = decrypt(message, key)
    else:
        # something here about a bad user input.

事实上,当你通过翻转钥匙的标志来考虑Caesar Cipher是可逆的时,你可以简单地做:

    if choice == "encrypt":
        result = encrypt(message, key)
    elif choice == "decrypt":
        result = encrypt(message, key * (-1))

并且根本不写decrypt函数!