Cpt*_*rkt 7 python prompt input python-3.x
我经常要求用户输入.我总是在主执行脚本中"按需"编写提示.这有点难看,因为我经常要求跨多个脚本输入相同类型的输入,我的代码只是复制/粘贴提示循环.这是我过去做过的事情:
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
Run Code Online (Sandbox Code Playgroud)
我想创建一些可以被称为的东西:
username = prompt(prompt="Enter New Username: ",
default=None,
rules=["user_does_not_exist",
"valid_username"])
Run Code Online (Sandbox Code Playgroud)
然后提示函数看起来像:
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
Run Code Online (Sandbox Code Playgroud)
我正在考虑的另一种方法是制作一个Prompt类,它可以让结果更加灵活.例如,如果我想将"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()
Run Code Online (Sandbox Code Playgroud)
我正在考虑的另一个选择是制作个性化的提示并命名它们,每个提示都与我原来的代码类似.这实际上并没有改变任何东西.它只是用于从我的主执行代码中获取这些循环,这使得主执行代码更容易浏览:
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
Run Code Online (Sandbox Code Playgroud)
我意识到,对我所有的程序都采用一种可接受的"y/n"格式可能是个好主意,我会的.这只是为了表明,在我需要一个非常相似但略有不同的提示的情况下,它会导致大量的复制/粘贴代码(根本没有这种方法的灵活性).
编写干净,灵活且易于维护的用户提示的好方法是什么?
(我已经看到了这一点:要求用户输入,直到他们给出有效的响应和其他一些响应.我的问题不是如何获取输入并验证它,而是关于如何创建一个可以重复使用的灵活输入系统跨多个程序).
我曾经为类似的事情编写过一个函数。解释在文档字符串中:
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
Run Code Online (Sandbox Code Playgroud)
例子:
>>> 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
Run Code Online (Sandbox Code Playgroud)