跳至主要内容

Python 循环教程

一篇关于 Python 循环的全面入门教程。学习并练习 while 与 for 循环、嵌套循环、break 与 continue 关键字、range 函数等!
· 15分钟 阅读

使用 AI 探索

range Python

循环在 Python 以及其他编程语言中都非常重要,因为它们可以帮助您反复执行一段代码。您经常会遇到需要一段代码重复使用的情况,但又不希望一遍遍地写相同的代码行。

在本篇 Python 循环教程中,您将学习以下主题:

While 循环

当您开始学习编程时,while 循环大概是您最早接触到的循环之一。它也可以说是最直观好懂的:从名称上看,“while” 与“区间”或“一段时间”有关。而您已经知道,“loop(循环)”指的是一段会被反复执行的代码。

结合这些,您可以很容易理解 while 循环的定义:

while 循环是一种编程概念:在实现后,只要给定条件仍为真,就会一遍又一遍地执行一段代码。

上面的定义也凸显了在 Python 中构建 while 循环所需的三要素:

  • while 关键字;
  • 能求值为 True 或 False 的条件;以及
  • 您希望被反复执行的代码块

就这些而已!

如何在 Python 中编写 while 循环

既然您已经知道构建 while 循环需要哪些要素,接下来先看一个实际示例,然后再自己做练习!考虑下面的例子:

# Take user input
number = 2  

# Condition of the while loop
while number < 5 :  
    print("Thank you")
    # Increment the value of the variable "number by 1"
    number = number+1

# Thank you
# Thank you
# Thank you

上面的代码示例是一个非常简单的 while 循环:如果仔细想想,您之前读到的三个要素都在这里了:while 关键字,紧跟一个能求值为 True 或 False 的条件(number < 5),以及您希望反复执行的代码块:

print("Thank you")
number = number + 1

如果进一步看这段代码,您会发现有一个变量 number,其中存储了整数 2。由于 number 的值小于 5,您会打印 "Thank you" 并将 number 的值加一。只要 number 的值保持小于 5,您就会继续执行 while 循环中的两行代码:

"Thank you"
"Thank you"

在 number 的值等于 5 之前,您还会再打印两次 “Thank you”,此时条件不再为 True。因为条件此时为 False,您将退出 while 循环,如果程序还有其他代码则继续执行。在这个例子中,没有更多代码,程序会停止。

上述示例有点基础,您也可以加入条件判断(即 if 条件)来进一步定制。看下面这个例子:

# Take user input
number = 2 

# Condition of the while loop
while number < 5 :  
    # Find the mod of 2
    if number%2 == 0:  
        print("The number "+str(number)+" is even")
    else:
        print("The number "+str(number)+" is odd")

    # Increment `number` by 1
    number = number+1

# The number 2 is even
# The number 3 is odd
# The number 4 is even

现在,来练习一下!

编写一个函数 collatz(),让用户将一个整数输入到名为 number 的变量中。如果 number 是偶数,则打印 number/2 的结果。如果 number 是奇数,则 collatz() 应打印并返回 3 * number + 1。程序应当不断对 number 调用 collatz(),直到其返回 1。

注意:这实际上是 Collatz 序列的一个实现。简单来说,这是一个数学问题:选一个数字,反复进行上述计算,直到结果为 1。

下面是参考解法:

def collatz(number):
    # Is the mod of 2 equal to 0?
    if number % 2 == 0:
        print(number // 2)
        return number // 2

    # If the mod of 2 isn't equal to 0, print `3 * number + 1`
    elif number % 2 == 1:
        result = 3 * number + 1
        print(result)
        return result

# Input   
n = 5

# As long as `n` is not equal to `1`, run `collatz()`
while n != 1:
    n = collatz(int(n))

# 16
# 8
# 4
# 2
# 1

For 循环

处理 for 循环的方法可以与 while 循环相同。不出意外,“for loop(for 循环)”中的 “for” 指的是“进行若干次”。

牢记以上内容,您可以这样定义 for 循环:

for 循环是一种编程概念:在实现后,会基于一个序列,按照特定的次数一遍又一遍地执行一段代码。

与 while 循环相反,for 循环不涉及一个被持续检查的条件——您只是将一段代码重复执行指定次数。换句话说,while 循环只在条件为 True 时继续执行其中的代码块,而 for 循环仅按特定次数执行其中的代码块。这个“次数”由一个序列或有序列表决定。

您稍后会进一步了解 while 和 for 循环的区别,但现在,请专注于创建 for 循环所需的以下要素:

  • for 关键字
  • 一个变量
  • in 关键字
  • range() 函数,这是 Python 标准库中的内置函数,用于创建数字序列
  • 您希望反复执行的代码

Python 中的 for 循环

# Print "Thank you" 5 times
for number in range(5):
    print("Thank you")

# Thank you
# Thank you
# Thank you
# Thank you
# Thank you

如您所见,在这个小示例中,上一节看到的各个组件都再次出现了:for 关键字、变量 number、in 关键字、range() 函数,以及您希望多次执行的代码 print("Thank you")。

并不难,对吧?

我们再看一个 for 循环的例子,这次用两个变量来定义控制流程:

languages = ['R', 'Python',  'Scala', 'Java', 'Julia']

for index in range(len(languages)):
   print('Current language:', languages[index])

# Current language: R
# Current language: Python
# Current language: Scala
# Current language: Java
# Current language: Julia

可以看到,您以 for 关键字开启循环。接下来,使用变量 index 和 languages,in 关键字,以及 range() 函数来创建一个数字序列。此外,由于 languages 列表不是数值型,您还使用了 len() 函数。您希望反复执行的代码是一条打印语句,即 print('Current language :', languages[index])。

在上述循环中,您的意思是:对于 len(languages) 范围内的每一个索引,打印对应的数据科学编程语言。现在,len(languages) 是 5,所以这段代码也可以改写为:

for index in range(5):
    print('Current language:', languages[index])

# Current language: R
# Current language: Python
# Current language: Scala
# Current language: Java
# Current language: Julia

结果还是一样!

Python 中的 while 与 for 循环对比

让我们再次回顾最开始的 while 循环示例,来确定 while 与 for 循环到底有哪些不同。您已经知道区别在于是否有条件参与检查,但这如何体现在代码中?又该如何在两者之间切换?

# Take user input
number = 2  

while number < 5 :
    print("Thank you")
    # Increment `number` by 1
    number = number+1

# Thank you
# Thank you
# Thank you

您可以使用 for 循环以更可控的方式打印 “Thank you” 这条语句:

# Print "Thank you" 3 times
for number in range(3) :  
    print("Thank you")

# Thank you
# Thank you
# Thank you

看到没?把 while 循环改写为等价的 for 循环就是这么容易。

它如何工作的?其实很简单。

在 for 循环中,传给 range 函数的整数就是循环与执行 for 子句中代码的“范围”或次数。

注意:range() 函数的计数从 0 开始,而不是从 1 开始。这意味着在上面的例子中,计数是 0、1、2,而不是 1、2、3。这是计算机内存中的计数方式。所以在设计 for 循环时,请始终记住要从 0 开始考虑 range 的计数,而不是从 1 开始。

提示:Python 的列表也是一样。若想了解更多关于 Python 列表的内容,建议查看 DataCamp 的教程 18 Most Common Python List Questions。

另外,for 循环与 while 循环还有一个有趣的区别:for 循环更快。要理解这一点,请看下面的例子。

import timeit

# A for loop example
def for_loop():
    for number in range(10000) :  
        # Execute the below code 10000 times
        sum = 3+4
        #print(sum)

timeit.timeit(for_loop)

# 267.0804728891719
import timeit

# A while loop example
def while_loop():
    i =0
    while i<10000:
        sum = 3+4
        #print(sum)
        i+=1

timeit.timeit(while_loop)

# 884.9233417965908

在上面的代码段中,有两个循环,迭代次数都在 10000 左右。二者乍一看很像,但当您看看背后各自如何工作时就会明白不同之处。提示:timeit() 函数给出了线索!

请记住:所有 Python 代码都由 C 解释器处理,这意味着上面的代码会先被分解为字节码,然后由底层的 C 解释器处理。

当上面例子中的 for 循环开始执行时,Python 解释器会与底层的 C 解释器通信,并创建一个大小为 10000 的列表对象。接着,它调用迭代器,依次访问该列表中 10000 个元素的索引。

另一方面,while 循环的执行并不会创建任何列表对象。实际上,底层 C 解释器会对条件 i<10000 调用布尔比较操作 9999 次。

您可以想象,遍历一个已创建且含有 10000 个元素的列表对象,比反复进行 9999 次布尔运算要更轻松,因此 for 循环的时间性能优于 while 循环。这也清晰地体现在执行时间上:for 循环完成所需的时间明显少于 while 循环。

现在来试试 for 循环吧!请注意,您需要将范围设为 0 到 11,因为您只想显示斐波那契序列中到 55 为止的数字,55 是该序列的第 11 个数。

# Initialize `first_no` to `0`
first_no = 0

# Initialize `second_no` to `1`
second_no = 1

# Initialize `numbers`
numbers = ___________

# Find and display Fibonacci series
for num in _______:
           if(num <= 1):
           # Update only `nth`
                      nth = ___
           else:
           # Update the values `nth`, `first_no` and `second_no`
                      nth = first_no + second_no
                      first_no = second_no
                      second_no = __________
                      
           # Print `nth`
           print(nth)

嵌套循环

正如您在上面的示例中注意到的,while 循环中包含了 if-else 条件,这使您可以在代码中引入更多条件。

等等!

这并不是定制循环的唯一方式。您还可以在现有代码中再加入 while 循环,这被称为嵌套循环。您可以将上述示例修改为如下形式,加入另一个 while 循环:

# Take user input
number = 2 

# condition of the while loop
while number < 5 :  
    # condition of the nested while loop    
    while number % 2 == 0: 
        print("The number "+ str(number)+" is even")

在上面的例子中,还有一个 while 循环“嵌套”在外层循环中,这个内层循环加入了另外一个检查,以判断 number % (mod) 2 是否为 0。

换句话说,它会检查数字是否为偶数,然后打印 “The number is even”。

但这里有个问题:如果您仔细看,会发现与前面的代码不同,这里缺少 number=number+1 的语句。由于您没有在任何地方增加 number 变量的值,该变量的值每次都不变,代码会进入无限循环。也就是说,一旦进入循环,它就再也不会离开,并无限次打印这条语句,因为变量 number 将一直等于 2。显然,这个数字小于 5,且为偶数。

现在来看看嵌套 for 循环会是什么样子:

# Print the below statement 3 times
for number in range(3) :  
    print("-------------------------------------------")
    print("I am outer loop iteration "+str(number))
    # Inner loop
    for another_number in range(5):  
        print("****************************")
        print("I am inner loop iteration "+str(another_number))
-------------------------------------------
I am outer loop iteration 0
****************************
I am inner loop iteration 0
****************************
I am inner loop iteration 1
****************************
I am inner loop iteration 2
****************************
I am inner loop iteration 3
****************************
I am inner loop iteration 4
-------------------------------------------
I am outer loop iteration 1
****************************
I am inner loop iteration 0
****************************
I am inner loop iteration 1
****************************
I am inner loop iteration 2
****************************
I am inner loop iteration 3
****************************
I am inner loop iteration 4
-------------------------------------------
I am outer loop iteration 2
****************************
I am inner loop iteration 0
****************************
I am inner loop iteration 1
****************************
I am inner loop iteration 2
****************************
I am inner loop iteration 3
****************************
I am inner loop iteration 4

上述代码是第一个 for 循环示例的修改版。注意在外层循环内使用了第二个 for 循环。

继续运行这段代码。

您会发现控制流先进入第一个 for 循环,变量 number 的值被初始化为 0。第一条打印语句被打印,然后控制流进入第二个 for 循环,其中变量 another_number 的值被初始化为 0。第二个 for 循环中的第一条打印语句被打印一次。

接着,控制流再次回到内层 for 循环,another_number 的值被重新初始化为下一个整数,并打印 print() 函数中的语句。

上述过程会持续,直到控制流遍历完 range() 函数的末尾(此处为 5),然后控制流返回到最外层循环,将变量 number 初始化为下一个整数,打印 print() 函数中的语句,进入内层循环,并重复上述步骤,直到遍历完整个 range() 函数。

这种控制流从最外层循环,进入内层循环,再返回到外层循环的过程会一直持续,直到覆盖完整个范围(在您的示例中是 3 次)。

既然已经阅读了关于嵌套循环的一些解释,是时候亲自上手了!请编写一个 Python 程序,使用嵌套 for 循环构造如下图案:loops Python

# Initialize the first five rows
n = _

# Start the loop to print the first five rows
for i in range(_):
    for j in range(i):
        print('* ', end="")
    print('')

# Start the loop to print the remaining rows in decreasing order of stars
for i in range(n,0,-1):
    for j in range(_):
        print('* ', end="")
    print('')

break 和 continue 关键字:创建无限循环

您可以在任何循环中使用 break 和 continue。这些关键字并不只用于打破有意创建的无限循环,但应谨慎使用。两者都会让他人(包括几个月后回看自己代码的您)更难理解循环中的控制流以及条件结束的位置。此外,您并不一定需要使用 break 和 continue:正如您目前所见,不用它们也完全没问题!

不过,在某些情况下,编写有意的无限循环会比您之前看到的传统 for 和 while 循环更清晰。当然,在这些情况下,鼓励使用这些关键字!

在 Python 中中断与继续 while 循环

幸运的是,有一种方法可以跳出上述无限循环的情况,那就是使用 break 关键字。

# Take user input
number = 2 

# Condition of the while loop
while number < 5 :  
    # condition of the nested while loop
    while number % 2 == 0:  
        print("The number "+str(number)+" is even")
        break

    number+=1

当您运行上面的代码时,它就不会再进入无限循环了。

“这是什么魔法!” 您或许会惊呼——别急,这并不神秘。

发生的情况是:当控制流遇到 break 关键字时,它会明白需要退出循环(此处为内层循环),并执行下一行代码。因此它跳出内层 while 循环,回到外层循环,并在外层 while 循环条件为真时继续按常规执行。

您需要注意,break 关键字之后必须有一行代码,否则它不会产生任何效果。试着删除上例中 break 之后的那行代码,再运行看看。

如果您在 break 语句之后又“悄悄”加入了 continue 关键字会怎样?请看下面的代码:

number = 2 

while number < 5 :
    while number % 2 == 0: 
        print("The number "+str(number)+" is even")
        break

    continue

    number+=1

上面的代码是 break 示例的一点小改动。

当您运行上面的代码时,会再次遇到无限循环。在发愁之前,仔细看一眼。您会注意到在 break 后面有一个 continue。continue 的作用是把控制流直接转回到最外层循环,而且发生在变量 number 自增之前,因此代码又陷入了无限循环。

中断与继续 for 循环

如果您不想让上例中的内层 for 循环执行完整个范围怎么办?您可以像在 while 循环中那样使用 break 语句。

# Print the below statement 3 times
for number in range(3) : 
    print("-------------------------------------------")
    print("I am outer loop iteration "+str(number))
    for another_number in range(3):
        print("****************************")
        print("I am inner loop iteration "+str(another_number))
        break

在上面的例子中,内层循环后的 break 关键字会指示控制流跳出内层循环,然后控制流返回外层循环。

运行下面的代码示例:

# Print the below statement 3 times
for number in range(3) :  
    print("-------------------------------------------")
    print("I am outer loop iteration "+str(number))
    continue
    for another_number in range(3):
        print("****************************")
        print("I am inner loop iteration "+str(another_number))
        break

在上面的代码中,只有最外层循环被执行,控制流甚至不会进入内层循环。

“为什么?” 您可能会问。

仔细看看代码。在最外层循环的第二条打印语句后面有一个 continue 关键字。它的作用是指示控制流跳回外层 for 循环并重新开始,因此控制流从未进入内层循环。

与 while 循环不同,for 循环中在 break 关键字后并不需要再写一段代码。单独一个 break 在 for 循环中就能正常工作。

range() 与 xrange() 的比较

这两个函数彼此相似,但如果您使用的是 Python 3,就只能使用 range()。在 Python 3.x 中,xrange() 被更名为 range()。这意味着如果您在 Python 3 中尝试使用 xrange(),会得到 NameError: name 'xrange' is not defined 错误。

为理解这两个函数的相似之处,请看下面的例子:

# Print the below statement 3 times
for number in range(5,10,2) :  
    print("I am number : "+str(number))

# I am number : 5
# I am number : 7
# I am number : 9

运行上面的代码,您会看到变量 number 的值每次跳过 2,这正是因为 range() 函数中的参数设置。

该函数的第一个参数是起始参数,即控制开始计数的位置。第二个参数是终止参数,即控制需要停止的位置。最后一个参数是步长,定义了计数时每次跳过的幅度。

因此,在上面的例子中,控制从 5 开始,遍历到 9,每次计数加 2。也就是 5、5+2=7、7+2=9。

您已经了解了如何用 range() 函数来定义代码需要循环的次数。而在 Python 2.x 中,您还会发现另一种方式,即 xrange() 函数。运行下面的代码:

# Print the below statement 3 times
for number in xrange(10) :  
    print("I am number : "+str(number))
I am number : 0
I am number : 1
I am number : 2
I am number : 3
I am number : 4
I am number : 5
I am number : 6
I am number : 7
I am number : 8
I am number : 9

您看到上述代码与不使用 xrange() 的代码输出有什么不同吗?没有区别?

没错。您在代码输出上看不到任何差异。

那为什么还要使用 xrange()?本教程稍后会谈到这一点。先运行下面的代码:

print(xrange(10))
print(range(10))
xrange(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

您可以看到,在上述代码的输出中,两条打印语句的输出是不同的。在包含 xrange() 的打印语句中,打印的是 xrange() 函数对象。本例中带有 range() 的打印语句则不同:它打印的是从 0 到 9 的整数列表。

这正是 range() 与 xrange() 的区别所在。

当您使用 range() 时,整个范围的列表会被存储在内存(RAM)中并呈现给您。然而,当您使用 xrange() 时,列表并不会存储在内存中。相反,xrange() 会在需要时按需生成整个范围内的整数。通过这种方式,xrange() 有助于在资源紧张的系统中节省内存。

精进您的 Python 技能!

恭喜您读完本教程。现在,您已经学会了如何在 Python 中使用循环,继续动手实践吧。练得越多,越熟练!

主题