Most Pythonic way to do input validation
本问题已经有最佳答案,请猛点这里访问。
在Python中,用户输入验证最"正确"的方法是什么?
我一直在使用以下功能:
1 2 3 4 5 6 7 8 | while True: stuff = input("Please enter foo:") try: some_test(stuff) print("Thanks.") break except SomeException: print("Invalid input.") |
我想这是一个很好的、可读性很强的函数,但是我不禁想知道是否没有内置函数或者我应该使用的函数。
我喜欢装饰师将检查与输入处理的其余部分分开。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/env python def repeatOnError(*exceptions): def checking(function): def checked(*args, **kwargs): while True: try: result = function(*args, **kwargs) except exceptions as problem: print"There was a problem with the input:" print problem.__class__.__name__ print problem print"Please repeat!" else: return result return checked return checking @repeatOnError(ValueError) def getNumberOfIterations(): return int(raw_input("Please enter the number of iterations:")) iterationCounter = getNumberOfIterations() print"You have chosen", iterationCounter,"iterations." |
编辑:
decorator或多或少是现有函数(或方法)的包装器。它接受现有的函数(在它的
对"用户输入"进行这种验证的最方法是捕获适当的异常。
例子:
1 2 3 4 5 6 7 8 9 | def get_user_input(): while True: try: return int(input("Please enter a number:")) except ValueError: print("Invalid input. Please try again!") n = get_user_input() print("Thanks! You entered: {0:d}".format(n)) |
允许异常发生在它们所在的位置,并允许它们冒泡,而不是隐藏它们,这样您就可以清楚地看到Python回溯中发生了什么问题,这也是一个很好的实践。
在本例中,验证用户输入——使用python的duck类型并捕获错误。如果它像管道一样,那一定是鸭子。(如果它的行为类似于int,则必须是int)。
有点复杂,但可能很有趣:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import re from sys import exc_info,excepthook from traceback import format_exc def condition1(stuff): ''' stuff must be the string of an integer''' try: i = int(stuff) return True except: return False def condition2(stuff): ''' stuff is the string of an integer but the integer must be in the range(10,30)''' return int(stuff) in xrange(10,30) regx = re.compile('assert *\( *([_a-z\d]+)') while True: try: stuff = raw_input("Please enter foo:") assert(condition1(stuff)) assert ( condition2(stuff)) print("Thanks.") break except AssertionError: tbs = format_exc(exc_info()[0]) funky = globals()[regx.search(tbs).group(1)] excepthook(exc_info()[0], funky.func_doc, None) |
结果
1 2 3 4 5 6 7 8 9 | Please enter foo: g AssertionError: stuff must be the string of an integer Please enter foo: 170 AssertionError: stuff is the string of an integer but the integer must be in the range(10,30) Please enter foo: 15 Thanks. |
.
编辑我找到了一种简化方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from sys import excepthook def condition1(stuff): ''' stuff must be the string of an integer''' try: int(stuff) return True except: return False def another2(stuff): ''' stuff is the string of an integer but the integer must be in the range(10,30)''' return int(stuff) in xrange(10,30) tup = (condition1,another2) while True: try: stuff = raw_input("Please enter foo:") for condition in tup: assert(condition(stuff)) print("Thanks.") break except AssertionError: excepthook('AssertionError', condition.func_doc, None) |