Python 有两个循环结构。
while循环用于不确定次数(不计次)的迭代,for循环用于确定次数(计次)的迭代。
break、continue和else关键字用来定制循环的行为。
range()和enumerate()有助于循环计数和下标访问。
while循环while循环只要 loop expression或“测试”在boolean context中求值为True,就会持续执行,当它求值为False时终止:
# Lists are considered "truthy" in a boolean context if they
# contain one or more values, and "falsy" if they are empty.
>>> placeholders = ["spam", "ham", "eggs", "green_spam", "green_ham", "green_eggs"]
>>> while placeholders:
... print(placeholders.pop(0))
...
'spam'
'ham'
'eggs'
'green_spam'
'green_ham'
'green_eggs'
for循环Python 中基本的 forloop 更应该称为 for each,它会遍历任意可迭代对象的值,当调用 next() 不再返回值(引发 StopIteration)时终止。
>>> word_list = ["bird", "chicken", "barrel", "bongo"]
>>> for word in word_list:
... if word.startswith("b"):
... print(f"{word.title()} starts with a B.")
... else:
... print(f"{word.title()} doesn't start with a B.")
...
'Bird starts with a B.'
'Chicken doesn\'t start with a B.'
'Barrel starts with a B.'
'Bongo starts with a B.'
range()
如果没有给定具体的iterable,就会用特殊的 range() 序列来充当循环计数器。range() 需要一个 int 来指定序列在哪里 stop,并且可以选择性地接受 start 和 step 形参。如果没有提供 start 数字,序列就会从 0 开始。range() 对象是惰性的(值按需生成),支持所有通用序列操作,而且无论指定的序列有多长,都只占用固定的内存。有意思的是,range()并不是迭代器,可以用在许多需要数字序列、却不涉及循环的场合。
# Here we use range to produce some numbers, rather than creating a list of them in memory.
# The values will start with 1 and stop *before* 7.
>>> for number in range(1, 7):
... if number % 2 == 0:
... print(f"{number} is even.")
... else:
... print(f"{number} is odd.")
'1 is odd.'
'2 is even.'
'3 is odd.'
'4 is even.'
'5 is odd.'
'6 is even.'
# range() can also take a *step* parameter.
# Here we use range to produce only the "odd" numbers, starting with 3 and stopping *before* 15.
>>> for number in range(3, 15, 2):
... if number % 2 == 0:
... print(f"{number} is even.")
... else:
... print(f"{number} is odd.")
...
'3 is odd.'
'5 is odd.'
'7 is odd.'
'9 is odd.'
'11 is odd.'
'13 is odd.'
enumerate() 获取值和下标如果同时需要值和下标,内置的 enumerate(<iterable>) 会返回一个遍历(index, value)值对的 iterator:
>>> word_list = ["bird", "chicken", "barrel", "apple"]
# *index* and *word* are the loop variables.
# Loop variables can be any valid python name.
>>> for index, word in enumerate(word_list):
... if word.startswith("b"):
... print(f"{word.title()} (at index {index}) starts with a B.")
... else:
... print(f"{word.title()} (at index {index}) doesn't start with a B.")
...
'Bird (at index 0) starts with a B.'
'Chicken (at index 1) doesn\'t start with a B.'
'Barrel (at index 2) starts with a B.'
'Apple (at index 3) doesn\'t start with a B.'
# The same method can be used as a "lookup" for pairing items between two lists.
# Of course, if the lengths or indexes don't line up, this doesn't work.
>>> word_list = ["cat", "chicken", "barrel", "apple", "spinach"]
>>> category_list = ["mammal", "bird", "thing", "fruit", "vegetable"]
>>> for index, word in enumerate(word_list):
... print(f"{word.title()} is in category: {category_list[index]}.")
...
'Cat is in category: mammal.'
'Chicken is in category: bird.'
'Barrel is in category: thing.'
'Apple is in category: fruit.'
'Spinach is in category: vegetable.'
enumerate(<iterable>) 函数还可以设置 start,让下标从另一个数字开始计数:
# Here, the index count will start at 1.
>>> for position, word in enumerate(word_list, start=1):
... if word.startswith("b"):
... print(f"{word.title()} (at position {position}) starts with a B.")
... else:
... print(f"{word.title()} (at position {position}) doesn't start with a B.")
...
'Bird (at position 1) starts with a B.'
'Chicken (at position 2) doesn\'t start with a B.'
'Barrel (at position 3) starts with a B.'
'Apple (at position 4) doesn\'t start with a B.'
continue关键字可以用来跳到下一个迭代周期:
>>> word_list = ["bird", "chicken", "barrel", "bongo", "sliver", "apple", "bear"]
...
... # This will skip *bird*, at index 0
... for index, word in enumerate(word_list):
... if index == 0:
... continue
... if word.startswith("b"):
... print(f"{word.title()} (at index {index}) starts with a b.")
...
'Barrel (at index 2) starts with a b.'
'Bongo (at index 3) starts with a b.'
'Bear (at index 6) starts with a b.'
break(和许多 C 系语言一样)关键字可以用来停止迭代,并“跳出”最内层的loop:
>>> word_list = ["bird", "chicken", "barrel", "bongo", "sliver", "apple"]
>>> for index, word in enumerate(word_list):
... if word.startswith("b"):
... print(f"{word.title()} (at index {index}) starts with a B.")
... elif word == "sliver":
... break
... else:
... print(f"{word.title()} doesn't start with a B.")
... print("loop broken.")
...
'Bird (at index 0) starts with a B.'
'Chicken doesn\'t start with a B.'
'Barrel (at index 2) starts with a B.'
'Bongo (at index 3) starts with a B.'
'loop broken.'
循环的else子句是 Python 独有的,可以在迭代结束之后用于“收尾”或“总结”性的操作。如果迭代通过break终止,else关键字之后的语句就不会执行:
>>> word_list = ["bird", "chicken", "barrel", "bongo", "sliver", "apple"]
# Using enumerate to get both an index and a value.
>>> for index, word in enumerate(word_list):
... word = word.title()
... if word.startswith("B"):
... print(f"{word} (at index {index}) starts with a B.")
...
... # This executes once *StopIteration* is raised and
... # There are no more items to iterate through.
... # Note the indentation, which lines up with the for keyword.
... else:
... print(f"Found the above b-words, out of {len(word_list)} words in the word list.")
...
'Bird (at index 0) starts with a B.'
'Barrel (at index 2) starts with a B.'
'Bongo (at index 3) starts with a B.'
'Found the above b-words, out of 6 words in the word list.'
# Terminating a loop via *break* will bypass the loop *else* clause
>>> for index, word in enumerate(word_list):
... word = word.title()
... if word.startswith("B"):
... print(f"{word} (at index {index}) starts with a B.")
... if word.startswith("S"):
... print("Found an S, stopping iteration.")
... break
... # This statement does not run, because a *break* was triggered.
... else:
... print(f"Found the above b-words, out of {len(word_list)} words in the word list.")
...
'Bird (at index 0) starts with a B.'
'Barrel (at index 2) starts with a B.'
'Bongo (at index 3) starts with a B.'
'Found an S, stopping iteration.'