习题答案
作业一:使用 while 循环结构,因为需要在有评论时执行回复操作,没有评论时什么也不做。使用while True
形成一个死循环,然后在其中判断是否有新评论也是可行的,但考虑到运行效率,一般在实际场景中不这样编写程序。
作业二:由于 if 语句和 elif 语句的顺序颠倒,在分数介于 0 到 60 之间时,本应该输出不及格,但由于这个区间的数符合小于 90 的条件,所以直接进入了第一个分支。
正确代码如下:
if score < 60:
print("怎么会没及格呢?")
elif score < 90:
print("差一点就优秀了")
else:
print("优秀,继续加油!")
作业三,代码如下:
for i in range(100):
i = 1 + 1
if i % 2 == 0:
print(i)
这是使用当前学习到的知识可以编写的最优代码。
另外,这样也是可以的,但涉及到 Python 的高阶语法,暂且不做讲解,感兴趣的小伙伴可以尝试运行一下:
[print(i) for i in range(1, 101) if i % 2 == 0]
列表
承接上文,你尝试着输出了 0 到 100 中所有的偶数,但新的问题接踵而至:怎么存储它们呢?
难道要定义五十个变量?
既然你有这个需求,Python 的开发者也一定有对应的解决方法:使用列表。
列表也是一种变量,但它类似一个篮子,你可以在其中放入各种变量:布尔值、整数、浮点数、字符串,甚至另一个列表。
空列表用一对中括号表示,让我们来试一下:
a = []
当然,你也可以在列表定义时就向里面加入一些东西:
b = [True, 0, 666.66, "叶子", True]
在每个英文逗号后加入空格也是一种编程规范,不遵守不会导致错误。
注意不要把列表的名字定义成”list“,原因我们会在后文提到。
你可能注意到了,列表中的内容是可以重复的。
创建列表之后也可以向里面加入东西,代码如下:
a.append(False)
以上代码中,我们向刚刚创建的新列表中加入了一个布尔值 False,它将出现在列表末尾。
有增肯定有减,我们可以使用 remove() 函数从列表里删除内容:
b.remove(True)
print(b)
输出是[0, 666.66, '叶子', True]
。由此可见,当你要删除的元素在列表中不止一个时,只有第一个元素会被删除。
你也可以输出列表中的每一项,使用 for 循环:
for i in b:
print(i)
到这里,我们就可以解释 for 循环的工作原理了:每次循环开始前,从 in 后的列表中拿出一项,将其赋值给循环变量(在这里是 i)。
range() 函数也可以这样理解,它接收一个整数,生成由 0 到 n-1 中所有整数组成的列表。
现在思考一下,如果我们要从列表中查找一个特定的值,找到则输出 True,否则输出 False,应该如何实现呢?
是这样吗?
for i in b:
if i == "叶子":
print(True)
else:
print(False)
可以实现,但好像有些复杂了。
其实 Python 提供了一种简便的方法:使用 in 来判断一个元素是否在列表中:
if "叶子" in b:
print(True)
else:
print(False)
这里的 in 被叫做成员运算符,有点像从队伍里找人,也就是判断一个人是不是这个队伍里的”成员“。
既然说到了队伍,现在有人想要知道队伍里由多少人,该怎么办呢?
难道是这样?
sum = 0
for i in b:
sum = sum + 1
print(sum)
不,最好这样:
print(len(b))
len() 也是一个函数,它是英语中”length“的缩写,意为”长度“。
它的参数是一个列表,返回一个整数,代表这个列表中的元素个数。
这样做还有一个优点:当列表特别大时,使用 len() 函数获取元素个数比 for 循环要快得多,因为这是一个非常常用的操作,Python 对其进行了优化。
元组
这个词可能听起来有些陌生,它是一个不可变的列表。
列表,还不可变,这东西由什么用呢?我第一次看到它时也是这么想的。
在叙述它的用途之前,先来说说如何使用它。
c = ()
其实就是把列表的中括号换成了小括号。
注意,当元组里只有一个元素时,需要在这个元素的后面加上一个逗号,就像这样:
d = (1, )
但是,你不能对它进行任何改变,如果你尝试使用 append() 函数:
AttributeError: 'tuple' object has no attribute 'append'
这个错误信息告诉你它不能进行添加操作。同理,删除也不可以。
当然,你可以使用 len() 函数获取它其中的元素个数。
简单说一下元组相较于列表的优点:它的创建速度更快,而且占用内存空间更小。在一般的程序中,这两点并不会有决定性的意义,但当你要处理数万规模的、不会被改变的数据时,元组就派上用场了。
另外,虽然它本身不能被改变,但你可以在它其中嵌套一个列表,然后改变这个列表中的值。
但列表在元组里,我们怎么改变它呢?
索引
这个名词又是什么意思?
其实可以类比成队伍里一个人的位置,小明在第 1 个,小刚在第 2 位......
我们可以在一个列表或元组后加上一个中括号,其中填入一个整数,来获取对应位置的元素。
b = [True, 0, 666.66, "叶子", True]
print(b[1])
咦?输出结果为什么是 ”0“ 而不是 ”True“?
这是因为在列表和元组中,索引是从 0 开始的。现在你可以理解为什么 range() 函数生成的列表从 0 开始了吧。
所以,想要取第一个值应该这样做。
print(b[0])
最后一个值呢?当然可以用 len() 获取列表中的元素个数再进行处理,但有更简便的方法:
print(b[-1])
-1 就是倒数第一个,-2 是倒数第二个,以此类推,是不是简单多了?
可以用一张图来直观展示列表中值与对应索引的关系:
image这个简单的图表也是用 Python 生成的,代码实现可以暂时忽略。
切片
简单理解,就是从列表或者元组里取一部分。
一直说”列表和元组“有点麻烦,干脆给这些变量取个名字,就叫”可迭代对象“好了,因为它们都可以用 for 循环进行迭代,也就是把里面的元素依次拿出来使用。
切片的语法很简单,但其中有几个坑需要我们注意:
b = [True, 0, 666.66, "叶子", True]
print(b[2:4])
猜猜这段代码输出什么?是[666.66, '叶子']
,第三个和第四个元素。
因为切片是左闭右开的,也就是说包含开始的那个元素,但不包含结束的那个元素,是不是有点像 range()?
所以,按照索引为 0 的规则,从索引 2 开始,取 2 和 3,不取 4。
如果我偷个懒,只写切片开始的位置,不写结束的位置,或者反过来,会发生什么?
b = [True, 0, 666.66, "叶子", True]
print(b[2:])
print(b[:4])
以下是输出结果:
[666.66, '叶子', True]
[True, 0, 666.66, '叶子']
可以看出,不写开始位置时,默认从开头开始取,等效于开始位置写 0;不写结束位置时,默认取到结尾,等效于结束位置写len() + 1
。
现在我们来极致偷个懒,开头结尾都不写:
b = [True, 0, 666.66, "叶子", True]
print(b[:])
大家可能已经猜到了,输出结果和 b 一模一样,也就是说,在开头结尾都不写的情况下,输出原列表。
但事实上现在输出的列表,和原先的列表 b 已经没有了任何关系,只是它们含有的元素完全相同罢了。
所以,如果你使用==
进行比较,它们是相等的,但如果改变其中一个的值,另一个不会一起改变。
这涉及到深拷贝和浅拷贝的问题,我们暂且略过。
字典
对,就是大家平时用的那个字典。
想想我们是怎么查字典的,以英汉字典为例:先找到单词首字母对应的位置,然后找到单词,一个单词可能有多个中文含义。
在 Python 里面,我们把查字典所寻找的单词叫做”键“,把中文含义叫做”值“。
键是不可变的,但值可变;一个键可以对应多个值。
说到不可变,看看前面的内容,想到了什么?是的,元组可以做字典的键,但列表不可以。
注意,如果使用元组作为字典的键,这个元组中不能含有列表,必须保证它其中的所有元素都不可变。
我们使用大括号来创建一个列表,键和值之间用引号隔开,每一项之间用逗号分隔:
article = {
"title": "叶子带你学 Python",
"reads_count": 666,
"likes_count": 50,
"fp_amount": 88.88
}
现在我们要查字典了,如果我想获取文章标题,可以这样做:
print(article[title])
其实就是把列表的索引换成了字典的键。
在字典中添加一项,可以这样:
article["author"] = "初心不变_叶子"
是不是有点像定义变量?顺便说一句,你也可以用类似的方式修改列表中特定位置的值。
对字典中值的删除并不是使用 remove(),具体方法我们会在后文讲到。
其实,字典还有三个非常有用的函数,分别是keys()
、values()
和items()
,让我们来试试:
print(article.keys())
print(article.values())
print(article.items())
输出结果:
dict_keys(['title', 'reads_count', 'likes_count', 'fp_amount'])
dict_values(['叶子带你学 Python', 666, 50, 88.88])
dict_items([('title', '叶子带你学 Python'), ('reads_count', 666), ('likes_count', 50), ('fp_amount', 88.88)])
好像有些奇怪,但可以大体看出,前两个函数输出列表,分别是字典中所有的键和所有的值。
第三个函数输出的也是一个列表,但在列表中是一个个元组,分别代表字典中的键和它们所对应的值。
事实上,这些输出不是真正的列表,而是一些对象,只不过它们的操作和列表的操作几乎一致。
简单说一下字典的优点:它是 Python 中实现键值查找的最简单方式,同时由于它的使用场景,其查找速度极快,且不会因为字典中元素的增多而变慢。
课后作业
这篇文章中,我们学习了 Python 中三种最常用的、可以包含其它变量的变量类型。事实上,它们的专业叫法是”数据类型“,因为这些变量本质上都是有名字的数据。
作业一:请问元组里可以嵌套列表吗?
作业二:指出以下程序中的错误(共有 3 处):
a = [1, 2, 3. 4]
b = (True)
for i in a:
if i in b == False:
b.append(i)
作业三:给定以下列表:
a = [1, 1, 2, 2, 2, 3, 3, 3, 4, 4]
请编写程序,删除其中的所有偶数。
提示:使用 if 和 % 操作符判断是否是偶数,注意 remove() 在列表中有多个待删除元素时的行为,可以使用成员操作符 in 判断是否仍有元素未被删除。
网友评论