首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python 3 Vigenere密码

Python 3 Vigenere密码
EN

Code Review用户
提问于 2020-11-02 05:18:59
回答 1查看 1.3K关注 0票数 6

我对Python还是相当陌生的,我试图看看我是否有效地使用了模块、函数等,或者是否有另一种/更简单的方法来完成某些事情。

这个Python 3 Vigenere密码是一个基于JavaScript的密码的重新构建,并基于Windows。它接受任何字母表字符,并内置演示选项。密码演示使用的第一阶段的中央情报局氪星密码。

代码语言:javascript
复制
#! python
import os
import re

## Initialize global variables
continue_cipher = ""
demo_alphabet = "KRYPTOSABCDEFGHIJLMNQUVWXZ"
demo_key = "PALIMPSEST"
demo_cipher_string = "EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJYQTQUXQBQVYUVLLTREVJYQTMKYRDMFD"
demo_cipher_decoded = "BETWEENSUBTLESHADINGANDTHEABSENCEOFLIGHTLIESTHENUANCEOFIQLUSION"


## Visuals
def display_header():
    print("################################################")
    print("#                                              #")
    print("#            --- VIGENERE CIPHER ---           #")
    print("#                                              #")
    print("#   A simple Vigenere cipher decoder/encoder   #")
    print("#                                              #")
    print("################################################", end="\n\n")
    return
def display_results(mode, cipher_vars):
    # Clear screen for final results
    os.system('cls')

    # Display header
    display_header()

    # Decompose cipher_vars
    (alphabet, key, cipher_string, results) = cipher_vars

    print("Mode:", "Decrypt" if mode == "D" else "Encrypt", end="\n\n")
    print("Alphabet:", alphabet)
    print("Key:", key)
    print("Cipher String:", cipher_string, end="\n\n")
    print("Decoded string:" if mode == "D" else "Encoded string:", results, end="\n\n")
    return


## Validations
def string_is_alpha(input_string):
    return True if re.match("^[a-zA-Z_]*$", input_string) else False


## Cipher variables
def get_alphabet():
    global demo_alphabet

    while True:
        alphabet = input("Enter cipher alphabet: ").upper()
        if alphabet == "":
            alphabet = demo_alphabet
            break
        elif string_is_alpha(alphabet) is False:
            print("The alphabet is not valid. Alphabet should not contain spaces, digits or special characters.")
        else:
            break

    return alphabet
def get_key():
    global demo_key

    while True:
        key = input("Enter cipher key: ").upper()
        if key == "":
            key = demo_key
            break
        elif string_is_alpha(key) is False:
            print("The key is not valid. Key should not contain spaces, digits or special characters.")
        else:
            break

    return key
def get_cipher_string(mode):
    global demo_cipher_string
    global demo_cipher_decoded

    while True:
        cipher_string = input("Enter cipher string: ").upper()
        if cipher_string == "":
            cipher_string = demo_cipher_string if mode == "D" else demo_cipher_decoded
            break
        elif string_is_alpha(cipher_string) is False:
            print("The cipher string is not valid. Cipher strings should not contain spaces, digits or special characters.")
        else:
            break

    return cipher_string


## Cipher actions
def get_cipher_alphabets(alphabet, key):
    cipher_alphabets = []

    for char in key:
        char_index = alphabet.find(char)
        cipher_alphabet = alphabet[char_index:] + alphabet[:char_index]
        cipher_alphabets.append(cipher_alphabet)

    return cipher_alphabets
def start_cipher(mode, alphabet, key, cipher_string):
    mode_string = ""
    cipher_alphabets = get_cipher_alphabets(alphabet, key)
    
    cipher_alphabet_index = 0
    for char in cipher_string:
        # Reset cipher_alphabet_index to 0 when at end of cipher alphabets
        if cipher_alphabet_index == len(cipher_alphabets):
            cipher_alphabet_index = 0
        
        # Use appropriate alphabet based on mode
        # Syntax: base_alphabet[mode_alphabet.find(char)]
        if mode == "D":
            mode_string += alphabet[cipher_alphabets[cipher_alphabet_index].find(char)]
        else:
            mode_string += cipher_alphabets[cipher_alphabet_index][alphabet.find(char)]

        cipher_alphabet_index += 1

    return mode_string


## Cipher Mode
def get_cipher_mode():
    while True:
        cipher_mode = input("Choose cipher mode - [D]ecrypt or [E]ncrypt: ").upper()
        if cipher_mode != "D" and cipher_mode != "E":
            print("That is not a valid option. Please enter 'D' for decrypt and 'E' for encrypt.")
        else:
            break

    print("")
    return cipher_mode
def start_cipher_mode(mode):
    print("Press 'enter' to use demo options")
    alphabet = get_alphabet()
    key = get_key()
    cipher_string = get_cipher_string(mode)
    mode_string = start_cipher(mode, alphabet, key, cipher_string)
    return alphabet, key, cipher_string, mode_string


## Loop cipher
def get_continue_cipher():
    while True:
        continue_cipher = input("Do you want to decode/encode more? [Y/N]: ").upper()
        if continue_cipher != "Y" and continue_cipher != "N":
            print("That is not a valid option. Please enter 'Y' to continue and 'N' to quit.")
        else:
            break
    return continue_cipher


## Start vigenere cipher program
while continue_cipher != "N":
    # Clear the screen after each operation
    os.system('cls')

    # Display header
    display_header()

    # Determine cipher mode
    cipher_mode = get_cipher_mode()
    cipher_vars = start_cipher_mode(cipher_mode)

    # Display results
    display_results(cipher_mode, cipher_vars)

    continue_cipher = get_continue_cipher()
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-11-02 10:35:31

shebang

她应该是普通的。您目前正在调用python,它可能指向某些系统上的python2。

一个通用的、对虚拟环境友好的python shebang是:

代码语言:javascript
复制
#!/usr/bin/env python3

PEP-8

来自PEP-8指南的几点意见:

  • 用两行空白行包围顶层函数和类定义。
  • 在函数中使用空行,以指示逻辑节。
  • 常量通常在模块级别上定义,并以所有大写字母和下划线分隔单词。

PEP-484

类型提示函数使您更容易理解您的函数。看看佩普-484

if __name__

将脚本的执行逻辑放在if __name__ == "__main__"块中。一个更有描述性的解释可以检查论堆栈溢出

冗余逻辑

在您的代码中,您有5个不同的函数,只用于读取用户输入。所有这些人都有同样的工作:

  1. 无限回路
  2. 请求用户输入
  3. 转换为大写
  4. 验证输入是否为空(或在一组有效值中)
  5. 如果为空值,则返回默认值。
  6. 带值返回

所有这些都可以通过一个单一的函数来处理:

代码语言:javascript
复制
def ask_user_input(message: str, options: List[str] = None, default: str = None, check_alpha: bool = False) -> str:
    if not any([options, default]):
        raise ValueError("Either a set of `options` for validation or a fallback `default` needed.")
    while True:
        value = input(message).upper()
        if options:
            if value in options:
                break
            else:
                print(f"Invalid value. Select one of {', '.join(options)}")
                continue
        if default is not None:
            if not value:
                value = default
                break
            elif not check_alpha:
                break
            elif not (value.isalpha() and value.isascii()):
                print("The input text should only consist of ascii alphabets.")
                continue
            else:
                break
    return value

Regex/validation

验证输入的正则表达式允许使用_,而错误消息则明确表示没有特殊字符。上面重写的检查是使用(根据下面的注释更新)完成的:

代码语言:javascript
复制
value.isalpha() and value.isascii()

这将比regex执行得更快(除非用户不断输入错误的值10^ n 时间,在此时间预编译模式的性能可能略好一些)。

性能

为了使代码更具表现性,可以更改一些内容:

  1. 而不是连接(附加)到字符串mode_string,推到一个列表,最后,使用"".join()。更多细节论堆栈溢出
  2. 您也可以让您的程序支持linux (*nix)系统。对windows的唯一依赖是系统对cls的调用。也许(从堆栈溢出中提取):def ():os.system("cls“如果os.name == "nt”其他“清除”)
  3. 有两个名称非常相似的函数:start_cipher(mode...)start_cipher_mode(mode)。这使得很难知道哪一个是真正的starting密码。也许,有两个独立的函数encryptdecrypt
  4. 使用模块化操作,您可以删除以下条件: if cipher_alphabet_index == len(cipher_alphabets):cipher_alphabet_index =0,如:
  5. 由于您只使用alphabet字符串来实际处理其中字符的索引值,所以创建一个字典。字典中的查找与用于O(1) O(n) 相比是.find()。这将是:从迭代工具导入计数alphabet_map =dict(zip(字母表,count ()
  6. 从上面的两点来看,很明显,用户输入后并不需要真正的字符/字母表。只有指标值模块才重要。如果没有相当的数学理解,这可能很难理解/实现,所以您现在可以跳过这一点。
票数 7
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/251453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档