Loops
循环是一种重复执行某些代码的方法。
[1]
planets = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune']
for planet in planets:
print(planet, end=' ') # print all on same line
Mercury Venus Earth Mars Jupiter Saturn Uranus Neptune
注意for循环的简单性:我们指定我们想要使用的变量,我们想要循环的序列,并使用“in”关键字以直观和可读的方式将它们链接在一起。
“in”右侧的对象可以是支持迭代的任何对象。 基本上,如果它可以被认为是一个序列或事物的集合,可以循环它。 除了列表,我们也可以迭代元组中的元素:
[2]
multiplicands = (2, 2, 2, 3, 3, 5)
product = 1
for mult in multiplicands:
product = product * mult
product
360
甚至还可以迭代字符串中的每个字母:
[3]
s = 'steganograpHy is the practicE of conceaLing a file, message, image, or video within another fiLe, message, image, Or video.'
msg = ''
# print all the uppercase letters in s, one at a time
for char in s:
if char.isupper():
print(char, end='')
HELLO
range()
range()是一个返回数字序列的函数。 事实证明,编写循环非常有用。
例如,如果我们想重复一些动作5次:
[4]
for i in range(5):
print("Doing important work. i =", i)
Doing important work. i = 0
Doing important work. i = 1
Doing important work. i = 2
Doing important work. i = 3
Doing important work. i = 4
你可能认为range(5)返回列表[] 1, 2, 3, 4, 5] ,真是情况有点复杂。
[5]
r = range(5)
r
range(0, 5)
range返回“range object”。 它的行为很像列表(它是可迭代的),但不具备所有相同的功能。 正如我们在上一个教程中看到的那样,我们可以在像r这样的对象上调用help()来查看该对象的Python文档,包括它的所有方法。
[6]
help(range)
就像我们可以使用int(),float()和bool()将对象转换为另一种类型一样,我们可以使用list()将类似列表的东西转换为列表,这表示更熟悉(和有用) 的表示:
[7]
list(range(5))
[0, 1, 2, 3, 4]
请注意,范围从零开始,按照惯例,范围的顶部 不包括在输出中。 range(5)给出0到5但不包括5的数字。
这可能看起来像是一种奇怪的方式,但文档(通过help(range))提到的原因是:
range(4)产生0,1,2,3。这些正是4个元素列表的有效索引。
因此对于任何列表L,for i in range(len(L)):将迭代其所有有效索引。
[8]
nums = [1, 2, 4, 8, 16]
for i in range(len(nums)):
nums[i] = nums[i] * 2
nums
[2, 4, 8, 16, 32]
这是通过索引迭代列表或其他序列的经典方法。
另外:for i in range(len(L)):类似于其他语言中的for (int i = 0; i < L.length; i++)
enumerate
for foo in x 通过元素循环遍历列表,而for i in range(len(x))通过索引循环遍历列表。 如果你想两个都做怎么办?
输入枚举函数,这是Python隐藏的宝石之一:
[9]
def double_odds(nums):
for i, num in enumerate(nums):
if num % 2 == 1:
nums[i] = num * 2
x = list(range(10))
double_odds(x)
x
[0, 2, 2, 6, 4, 10, 6, 14, 8, 18]
给定一个列表,枚举返回一个对象,该对象通过列表的值和索引进行迭代。
(与range()函数一样,它返回一个可迭代对象。要将其内容作为列表查看,我们可以在其上调用list()。)
[10]
list(enumerate(['a', 'b']))
[(0, 'a'), (1, 'b')]
我们可以看到,我们迭代的东西是元组。 这有助于解释for i,num语法。 我们正在“解包”元组,就像上一个教程中的示例一样:
[11]
x = 0.125
numerator, denominator = x.as_integer_ratio()
我们可以在迭代元组集合时使用这种解包语法。
[12]
nums = [
('one', 1, 'I'),
('two', 2, 'II'),
('three', 3, 'III'),
('four', 4, 'IV'),
]
for word, integer, roman_numeral in nums:
print(integer, word, roman_numeral, sep=' = ', end='; ')
1 = one = I; 2 = two = II; 3 = three = III; 4 = four = IV;
这与下面的代码等价:
[13]
for tup in nums:
word = tup[0]
integer = tup[1]
roman_numeral = tup[2]
print(integer, word, roman_numeral, sep=' = ', end='; ')
1 = one = I; 2 = two = II; 3 = three = III; 4 = four = IV;
while loops
Python中另一类循环是while循环:
[14]
i = 0
while i < 10:
print(i, end=' ')
i += 1
0 1 2 3 4 5 6 7 8 9
while循环的参数被计算为布尔语句,并且直到语句求值为False时停止循环。
List comprehensions
列表解析是Python中最受欢迎和独特的功能之一,理解它的最简单的方式就是看一下例子:
[15]
squares = [n**2 for n in range(10)]
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
这里有一个不用列表解析的例子,效果是一样的:
[16]
squares = []
for n in range(10):
squares.append(n**2)
squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
我们也增加if条件:
[17]
short_planets = [planet for planet in planets if len(planet) < 6]
short_planets
['Venus', 'Earth', 'Mars']
(如果您熟悉SQL,可能会将其视为“WHERE”子句)
以下是使用if条件进行过滤并对循环变量应用某些变换的示例:
[18]
# str.upper() returns an all-caps version of a string
loud_short_planets = [planet.upper() + '!' for planet in planets if len(planet) < 6]
loud_short_planets
['VENUS!', 'EARTH!', 'MARS!']
人们通常把这些写在一行里,但是如果分成3行来写,结果会变得很清晰:
[19]
[
planet.upper() + '!'
for planet in planets
if len(planet) < 6
]
['VENUS!', 'EARTH!', 'MARS!']
继续SQL类比,您可以将这三行视为SELECT,FROM和WHERE
左边的表达式在技术上不必涉及循环变量(尽管它不是很常见)。 您认为以下表达式将做什么?
[20]
[32 for planet in planets]
列表解析与我们看到的一些函数(如min,max,sum,len和sorted)相结合,可以为一些问题提供一些令人印象深刻的单行解决方案,否则这些问题需要几行代码。
例如,最后一个练习包括一个脑力激荡器,要求你编写一个函数来计算列表中的负数,而不使用循环(或我们没有看到的任何其他语法)。 现在我们可以解决问题,因为我们的武器库中有循环:
[21]
def count_negatives(nums):
"""Return the number of negative numbers in the given list.
>>> count_negatives([5, -1, -2, 0, 3])
2
"""
n_negative = 0
for num in nums:
if num < 0:
n_negative = n_negative + 1
return n_negative
这有一个使用列表解析的办法:
[22]
def count_negatives(nums):
return len([num for num in nums if num < 0])
很好吧?
好吧,如果我们关心的是最小化代码的长度,那么第三种解决方案仍然更好!
[23]
def count_negatives(nums):
# Reminder: in the "booleans and conditionals" exercises, we learned about a quirk of
# Python where it calculates something like True + True + False + True to be equal to 3.
return sum([num < 0 for num in nums])
这些解决方案中哪一个是“最好的”完全是主观的。 使用较少的代码解决问题总是很好,但值得记住以下来自The Zen of Python的内容:
- 可读性很重要。
- 显式优于隐式。
count_negatives的最后一个定义可能是最短的,但阅读代码的其他人是否理解它是如何工作的?
编写Pythonic代码并不意味着永远不会使用for循环!
Your turn!
转到练习笔记本,进行循环和列表解析的练习。