软件自动化测试实战解析:基于Python3编程语言
上QQ阅读APP看书,第一时间看更新

2.13.4 循环的终止

循环让我们可以遍历一个集合。在很多情况下,遍历的目的是搜索和过滤某些特定的情况,在条件满足的时候,我们会结束循环。结束循环有一些细分的情况,对应的代码逻辑也会有差异,我们来逐一分析。

质数(prime number)是指一类特别的正整数,除了1和该数自身以外,它们不能被其他自然数整除。用代码来判断一个数是不是质数,最简单的思路就是用循环。


num = 102
print("Is '{}' a prime number?".format(num))
is_prime_number = True
for dividend in range(2, num):
    if num % dividend == 0:
        print(' - {}'.format(dividend))
        is_prime_number = False

print(is_prime_number)

执行结果如下:


Is '102' a prime number?
 - 2
 - 3
 - 6
 - 17
 - 34
 - 51
False

这段代码可以准确判断出102不是质数,因为它可以分别被2、3、6、17、34、51整除。要证明一个数不是质数,我们只需要找到一个可以整除它的数(除了1和它自身)就足够了。在找到了第一个这样的被除数以后,循环就没有必要继续了,在这种情况下,我们应该用break把后续的循环全部取消。


num = 102
print("Is '{}' a prime number?".format(num))

is_prime_number = True
for dividend in range(2, num):
    if num % dividend == 0:
        is_prime_number = False
        print(' - {}'.format(dividend))
        break

print(is_prime_number)

执行结果如下:


Is '102' a prime number?
 - 2
False

以上代码比较凌乱,我们可以设计一个函数,专门用于判断指定的数是不是质数。


def is_prime_number(num):
    is_prime_number = True
    for dividend in range(2, num):
        if num % dividend == 0:
            is_prime_number = False
            break

    return is_prime_number

重构后的函数也可以工作,只是在这种简单的循环函数中,我们可以用return来让代码更简化。


def is_prime_number(num):
    for dividend in range(2, num):
        if num % dividend == 0:
            return False

    return True

在以上范例中,我们不再创建额外的布尔类型变量,而是在发现第一个这样的整除数时,函数就返回布尔值False,表明这不是质数。如果整个循环都结束了都没有找到这样的整除数,函数就返回True,表明这是一个质数。

严格来说,return关键字并不是专门为循环设计的,而是为函数设计的,但是在一些包含循环逻辑的函数中,我们可以用return“立刻返回”的特性来结束循环。

基于以上代码,我们来看一个新的问题:有一个整数list,需要把其中的所有质数挑选出来,打印在屏幕上。很显然,我们需要用到循环逻辑,在遍历过程中,如果某个数不是质数,不需要对它做进一步处理,但是后续的循环还要继续,还要判断list中的其他数是不是质数。在这种情况下,我们需要用到continue关键字。


numbers = [101, 102, 103, 200, 29, 31, 301]
for num in numbers:
    if not is_prime_number(num):
        continue

    print('{} is prime number'.format(num))

一次循环迭代涉及的逻辑很可能不止一个步骤。在循环迭代中,continue表示跳过本次循环迭代的后续步骤开始下一个循环迭代。

接下来,我们看一个更复杂的问题。给定一个如下所示的二维list。


number_matrix = [
    [101, 102, 103],
    [787, 773, 751],
    [301, 307, 317],
    [721, 723, 743]
]

这个二维list的每一个元素都是一个整型数list,我们想把其中每个元素都是质数的子list挑选出来,这需要用到多重循环。


def get_prime_lists(number_lists):
    prime_lists = []
    for numbers in number_lists:

        non_prime_number_found = False
        for num in numbers:
            if not is_prime_number(num):
                print(' - {} is not a prime number in {}'.format(num, numbers))
                non_prime_number_found = True
                break

        if non_prime_number_found:
            continue

        prime_lists.append(numbers)

    return prime_lists

执行结果如下:


- 102 is not a prime number in [101, 102, 103]
 - 301 is not a prime number in [301, 307, 317]
 - 721 is not a prime number in [721, 723, 743]
[787, 773, 751]

从结果来分析程序逻辑,我们可以看到:在多重循环中使用的break语句,只会结束它直接所在的那一层循环,不会影响更外层的循环逻辑。

以上代码主要演示的是循环的控制,对于质数的判断逻辑不够严谨,读者可以自行改进。