在Python循环中继续使用时执行通用代码的模式
问题描述:
validate_input():
while not_valid:
attempt += 1
inpt = prompt_and_get_input()
if validate_check1(inpt) is False:
# common code for invalid_state
continue
if validate_check2(inpt) is False:
# common code for invalid_state
continue
# ... repeat ....
not_valid = False # Valid state
我想分解重复的通用代码,并将它放在循环中的单个位置。我明白我可以把它放在一个函数/方法中,但是仍然会有重复的调用。在Python循环中继续使用时执行通用代码的模式
我想这样做:
validate_input():
while not_valid:
attempt += 1
inpt = prompt_and_get_input()
if validate_check1(inpt) is False:
continue
if validate_check2(inpt) is False:
continue
# ... repeat ....
not_valid = False # Valid state
else:
# We get here anytime a validate_check() fails via continue
# common vode for _invalid_state
我明白,如果循环正常执行一个循环的else
子句将只执行(与通过break
)。我想那种在xxx
子句只得到事件的循环没有重复自然执行相反的功能(即continue
语句)
我知道有没有内置的功能,此功能,但是我有什么更好的模式?这个模式在我正在进行的项目中已经出现了好几次。
答
您可以在try/except块中使用异常。
class ValidationError(Exception):
pass
while not_valid:
try:
inpt = prompt_and_get_input()
if not validate_check1(inpt):
raise ValidationError()
...
except ValidationError:
# common code
更妙的是,提高validate_checkX函数中的验证错误,那么你甚至不需要检查返回值 - 甚至是返回一个值的。
(请注意,如果你返回一个值,这是非常unPythonic假比较。你应该做if not <whatever>
正如我在上面)
答
在我看来你输入的验证应该从一个地方进行管理,例如:
def is_valid(input, validators, reaction=None):
# type: AnyStr, Iterable[Callable[AnyStr, bool]], Callable[AnyStr] -> bool
for validator in validators:
if validator(input):
continue
if reaction:
reaction(input) # You could use partial to modify the reaction
return False
return True
谢谢。我已经使用了Python几个月,但它似乎仍然是非直观的,甚至不自然的引发异常,这不是真正的错误。我知道这是Pythonic的方式,现在我只需要记住编码。 – BrianHVB