在Python循环中使用continue时执行公共代码的模式

时间:2016-04-24 20:26:13

标签: python python-3.x design-patterns

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

我想将重复的公共代码分解出来,并将其放在循环中的单个位置。我知道我可以把它放在一个函数/方法中,但仍然会有重复的调用。

我想做点什么:

    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语句)

我知道此功能没有内置功能,但是我想要做的更好的模式是什么?在我正在进行的项目中,这种模式出现了好几次。

2 个答案:

答案 0 :(得分:1)

您可以在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函数中引发验证错误,然后你甚至不需要检查返回值 - 甚至根本不返回值。

(请注意,如果你确实返回了一个值,那么与False进行比较是非常不便的;如上所示,你应该if not <whatever>。)

答案 1 :(得分:0)

在我看来,您的输入验证应该在一个地方进行管理,例如:

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