python - 编写简洁、灵活且易于维护的用户输入提示

标签 python python-3.x input prompt

我经常负责征求用户的意见。我总是在我的主要执行脚本中“按需”编写提示。这有点丑陋,因为我经常要求跨多个脚本输入相同类型的内容,所以我的大量代码只是复制/粘贴提示循环。这是我过去所做的:

while True:
    username = input("Enter New Username: ")
    if ldap.search(username):
        print "   [!] Username already taken."
    if not validator.validate_username(username):
        print "   [!] Invalid Username."
    else:
        break

我想创建一个可以这样调用的东西:

username = prompt(prompt="Enter New Username: ",
                  default=None,
                  rules=["user_does_not_exist",
                         "valid_username"])

那么提示函数是这样的:

def prompt(prompt, default, rules):
    while True:
        retval = input(prompt)
        if default and retval == "":
            break
            return default
        if not rule_match(retval, rules):
            continue
        break
        return retval

def rule_match(value, rules):
    if "user_does_not_exist" in rules:
        if not user.user_exists(value):
            return False

    if "valid_username" in rules:
        if not validator.username(value):
            return False

    if "y_n_or_yes_no" in rules:
        if "ignore_case" in rules:
            if value.lower() not in ["y", "yes", "n", "no"]:
                return False
        else:
            if value not in ["y", "yes", "n", "no"]:
                return False

    return True

我正在考虑的另一种方法是创建一个 Prompt 类,这将使结果具有更大的灵 active 。例如,如果我想将“y”或“n”转换为 True 或 False,上述方法实际上不起作用。

create_another = Prompt(prompt="Create another user? (y/n): ,"
                       default=False,
                       rules=["y_n_or_yes_no",
                              "ignore_case"]).prompt().convert_to_bool()

我正在考虑的另一种选择是制作个性化的提示并为其命名,每个提示的编写都与我的原始代码相似。这实际上并没有改变任何东西。它只是用于将这些循环从我的主要执行代码中移除,这使得主要执行代码更易于浏览:

username = prompt("get_new_username")

def prompt(prompt_name):
    if prompt_name == "get_new_username":
        while True:
            username = input("Enter New Username: ")
            if ldap.search(username):
                print "   [!] Username already taken."
            if not validator.validate_username(username):
                print "   [!] Invalid Username."
            else:
                break
                return username

    if prompt_name == "y_n_yes_no_ignore_case":
        # do prompt
    if prompt_name == "y_n_yes_no":
        # do prompt
    if prompt_name == "y_n":
        # do prompt
    if prompt_name == "y_n_ignore_case":
        # do prompt
    if prompt_name == "yes_no":
        # do prompt 
    if prompt_name == "yes_no_ignore_case":
        # do prompt 

我意识到为我的所有程序确定一种可接受的“y/n”格式可能只是一个好主意,我会的。这只是为了表明,在我需要非常相似但略有不同的提示的情况下,它会导致大量复制/粘贴代码(此方法完全没有灵 active )。

编写简洁、灵活且易于维护的用户提示的好方法是什么?

(我看过这个:Asking the user for input until they give a valid response 和其他一些回复。我的问题不是关于如何获取输入并验证它,而是关于如何制作一个可以跨多个程序重复使用的灵活输入系统)。

最佳答案

我曾经为类似的东西写过一个函数。解释在文档字符串中:

def xory(question = "", setx = ["yes"], sety = ["no"], setz = [], strict = False):
    """xory([question][, setx][, sety][, setz][, strict]) -> string

    Asks question.  If the answer is equal to one of the elements in setx,
    returns True.  If the answer is equal to one of the elements in sety,
    returns False.  If the answer is equal to one of the elements in setz,
    returns the element in setz that answer is equal to.  If the answer is
    not in any of the sets, reasks the question.  Strict controls whether
    the answer is case-sensitive.  If show is True, an indication of the
    acceptable answers will be displayed next to the prompt."""

    if isinstance(setx, str):
        setx = [setx]
    if isinstance(sety, str):
        sety = [sety]
    if isinstance(setz, str):
        setz = [setz]
    if (setx[0])[0] != (sety[0])[0]:
        setx = [(setx[0])[0]] + setx
        sety = [(sety[0])[0]] + sety
    question = question.strip(" ") + " "
    while True:
        if show:
            shows = "[%s/%s] " % (setx[0], sety[0])
        else:
            shows = ""
        user_input = raw_input(question + shows)
        for y in [setx, sety, setz]:
            for x in y:
                if (user_input == x) or ((not strict) and (user_input.lower() == x.lower())):
                    if y is setx:
                        return True
                    elif y is sety:
                        return False
                    else:
                        return x
        question = ""
        show = True

例子:

>>> response = xory("1 or 0?", ["1", "one", "uno"], ["0", "zero", "null"], ["quit", "exit"])
1 or 0? x
[1/0] eante
[1/0] uno
>>> print(response)
True
>>> response = xory("Is that so?")
Is that so? Who knows?
[y/n] no
>>> print(response)
False
>>> response = xory("Will you do it?", setz=["quit", "exit", "restart"])
Will you do it? hm
[y/n] quit
>>> print(response)
quit

关于python - 编写简洁、灵活且易于维护的用户输入提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35352232/

相关文章:

python - 避免空列表的默认参数的pythonic方法是什么?

django - Django 管理站点中的不同字段集取决于用户组

python - 如何在元类中键入提示动态设置的类属性?

python - 在每行中找到最后一个元素(数字)并对所有偶数求和 python 3

javascript - 如何在我的输入表单中阻止 html 和 url

python - Enthought - Canopy Express 安装问题 (Windows 7 x64)

python - Django modelform 中的某些字段未更新

python - 如何在 Pygame 中获取用户的输入并将其保存为变量?

javascript - 如何从变量名来自用户输入的数组中动态检索数据

python - 如何创建一个 os.walk() 函数来比较两个目录的文件夹和子文件夹?