启动文件
下载 lab01.zip。在存档中,您将找到本实验中问题的开始文件,以及 Ok 自动打分器的副本。
此外, 如果您在《实验 0:Python 的安装》或使用 Windows 自动安装程序时遇到任何问题,请填写此调查。
为了快速生成 ok 命令,您现在可以使用 ok 命令生成器。
快速回顾
使用 Python
运行 Python 文件时,您可以使用命令行的选项进一步检查代码。这里有一些会派上用场。如果您想了解其他 Python 命令行选项的更多信息,请查看文档。
-
不使用命令行选项将运行您提供的文件中的代码然后返回到命令行。例如,如果我们想以这种方式运行
lab00.py
,我们可以在终端中输入:python3 lab00.py
-
-i
:使用-i
选项将运行您的 Python 脚本,然后打开一个交互式会话。在交互式会话中,您逐行运行 Python 代码并获得即时反馈,而不是一次运行整个文件。要退出的话,请在解释器提示符键入exit()
。您还可以在 Linux/Mac 计算机上使用Ctrl-D
或Windows上使用Ctrl-Z Enter
等键盘快捷键。如果在交互运行时编辑 Python 文件,则需要退出并重新启动解释器以使这些更改生效。
以下是我们如何以交互方式运行
lab00.py
:python3 -i lab00.py
-
-m doctest
: 在特定文件中运行文档测试。文档测试被函数内的三重引号 ("""
)包围。文件中包含
>>>
的每个测试都跟随这一些 Python 代码和预期的输出(尽管>>>
在文档测试命令的输出中看不到)。要运行`
lab00.py
的文档测试,我们可以运行:python3 -m doctest lab00.py
使用 OK
在 CS 61A 中,我们使用名为 Ok 的程序对实验、作业和项目进行自动评分。您在本实验开始时下载的启动文件中已经有了 Ok。有关使用 Ok 命令的更多信息,请在此处了解。
您可以在 ok-help 快速生成大多数 ok 命令 。
要使用 Ok 为指定的函数运行文档测试,请运行以下命令:
python3 ok -q <specified function>
默认情况下,只会显示未通过的测试。您可以使用-v
选项显示所有测试,包括您已通过的测试:
python3 ok -v
您还可以通过编写一下语句在 OK 中使用调试打印功能
print("DEBUG:", x)
最后,当您完成 lab01.py 中的所有问题后 ,您必须使用--submit
选项提交作业 :
python3 ok --submit
结对编程
您可以将此实验用作尝试结对编程的一种方式。请查看 结对编程页面。
主题
如果您需要复习本实验的材料,请参阅此部分。你可以直接跳到问题部分,如果你遇到困难,可以回来参考这里。
除法、整除和模
让我们比较一下 Python 3 中不同的除法相关的运算符:
真正的除法:(/ 十进制除法) |
向下取整除法:(// 整除) |
模:(% 求余数) |
---|---|---|
>> 1 / 5 0.2 >> 25 / 4 6.25 >>> 4 / 2 2.0 >>> 5 / 0 ZeroDivisionError |
>>> 1 // 5 0 >>> 25 // 4 6 >>> 4 // 2 2 >>> 5 // 0 ZeroDivisionError |
>>> 1 % 5 1 >>> 25 % 4 1 >>> 4 % 2 0 >>> 5 % 0 ZeroDivisionError |
请注意,某些情况下 Python 会输出ZeroDivisionError
。我们稍后将在本实验室的“错误信息”部分对此进行讨论。
一种关于%
运算符的有用方法是检查一个数字x
是否可以被另一个数字y
整除:
x % y == 0
例如,为了检查x
是否是偶数:
x % 2 == 0
函数
如果我们想一遍遍地执行一系列语句,我们可以将它们抽象成一个函数以避免重复写代码。
例如,假设我们想知道将数字 1 到 3 乘以 3 然后加上 2 的结果。这是一种方法:
>>> 1 * 3 + 2
5
>>> 2 * 3 + 2
8
>>> 3 * 3 + 2
11
如果我们想用更大的一组数字来做这件事,那将是大量重复的代码!让我们编写一个函数来捕获此操作,考虑到任何输入数字。
def foo(x):
return x * 3 + 2
这个名为 foo
的函数接受一个参数,并将返回将该参数乘以 3 并加上 2 的结果。
现在我们可以在需要运算时调用此函数:
>>> foo(1)
5
>>> foo(2)
8
>>> foo(1000)
3002
将函数应用于某些参数是通过调用表达式完成的。
调用表达式
调用表达式应用一个函数,该函数可能接收也可能不接收参数。调用表达式计算结果为函数的返回值。
函数调用的语法:
add ( 2 , 3 )
| | |
operator operand operand
每个调用表达式都需要一组括号来限定其以逗号分隔的操作数。
要求值函数调用:
- 计算运算符,然后是操作数(从左到右)。
- 将运算符应用于操作数(操作数的值)。
如果操作数是嵌套调用表达式,则首先将这两个步骤应用于该内部操作数,以便评估外部操作数。
return
和 print
您定义的大多数函数都将包含一个return
语句。该return
语句将一些计算的结果返回给函数的调用者并退出当前函数。例如,下面的函数square
接受一个数字x
并返回它的平方。
def square(x):
"""
>>> square(4)
16
"""
return x * x
当 Python 执行一条return
语句时,函数立即终止。如果 Python 在没有执行return
语句的情况下到达函数体的末尾,它会自动返回None
.
相反,print
函数用于在终端中显示值。这可能会导致print
和return
之间的一些混淆,因为在 Python 解释器中调用函数将打印出函数的返回值。
然而,不同于return
声明,当 Python 计算一个print
表达式时,函数并不会立即终止。
def what_prints():
print('Hello World!')
return 'Exiting this function.'
print('61A is awesome!')
>>> what_prints()
Hello World!
'Exiting this function.'
还要注意,
return
会保留引号。
控制
布尔运算符
Python 支持的三种布尔运算符:and
、or
和not
:
>>> a = 4
>>> a < 2 and a > 0
False
>>> a < 2 or a > 0
True
>>> not (a > 0)
False
and
:只有当两个操作数计算结果都为True
,and
的计算结果才为True
。如果至少有一个操作数是False
, 则and
计算结果为False
。or
:如果至少一个操作数计算为True
,则or
计算结果为True
。如果两个操作数都是False
,则计算结果为False
。not
:如果其操作数计算为True
,则结果为False
。如果其操作数计算为False
,则结果为True
。
您认为以下表达式的计算结果是什么?在 Python 解释器中尝试一下。
>>> True and not False or not True and False
很难阅读如上面的复杂的表达式,也很难理解程序的行为方式。使用括号可以使您的代码更容易理解。Python 以下列方式解释该表达式:
>>> (True and (not False)) or ((not True) and False)
这是因为布尔运算符和算术运算符一样,也有一个运算顺序:
not
具有最高优先级and
or
具有最低优先级
真假值:事实证明and
、or
不仅仅适用于布尔值 ( True
, False
)。诸如0
, None
, ''
(空字符串)和[]
(空列表)之类的 Python 值被视为假值。而所有其他值都被视为真值。
短路
如果我们在 Python 中输入以下内容,您认为会发生什么?
1 / 0
用 Python 试试吧!你应该看到一个ZeroDivisionError
. 但是这个表达呢?
True or 1 / 0
它的结果为True
,因为 Python and
和or
运算符会短路。也就是说,它们不一定求值每个操作数。
运算符 | 检查是否: | 从左到右求值直到: | 例子 |
---|---|---|---|
AND | 所有值都为真 | 第一个假值 | False and 1 / 0 求值为 False |
OR | 至少有一个值为真 | 第一个真值 | True or 1 / 0 求值为 True |
当运算符到达能够对表达式得到结果的操作数时,就会发生短路。例如,and
一旦达到第一个假值就会短路,因为它知道并非所有值都为真。
如果and
和or
不短路,它们就返回最后一个值;另一种记住这一点的方法是,无论是否短路and
,or
始终返回求值的最后结果。请记住,使用比其它值时,当使用除了True
和False
的其他值时,and
和or
并非总是返回布尔值。
条件语句
您可以在《Composing Programs》的1.5.4节中查看if
语句的语法。
提示:我们有时会看到如下所示的代码:
if x > 3: return True else: return False
这可以更简洁地写成
return x > 3
. 如果你的代码看起来像上面的代码,看看你能不能更清晰地重写它!
While 循环
您可以在《Composing Programs》的1.5.5节中查看while
循环的语法。
错误信息
到现在为止,您可能已经看到了一些错误信息。它们可能看起来令人生畏,但错误消息对于调试代码非常有帮助。以下是一些常见的错误类型:
错误类型 | 说明 |
---|---|
SyntaxError | 包含不正确的语法(例如,if 语句后缺少冒号或忘记右括号/引号) |
IndentationError | 包含不正确的缩进(例如,函数体的缩进不一致) |
TypeError | 尝试对不兼容的类型进行操作(例如尝试对函数和数字使用加法)或使用错误数量的参数调用函数 |
ZeroDivisionError | 试图除以零 |
使用这些错误消息的说明,您应该能够更好地了解代码出了什么问题。如果遇到错误信息,请在寻求帮助之前尝试确定问题。你可以经常谷歌不熟悉的错误信息,看看其他人是否也犯过类似的错误来帮助你调试。
例如:
>>> square(3, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: square() takes 1 positional argument but 2 were given
笔记:
- 错误消息的最后一行告诉我们错误的类型。在上面的例子中,我们有一个
TypeError
. - 错误消息告诉我们做错了什么——
square
当它只能接受 1 个参数时,我们给出了2 个参数。一般来说,最后一行是最有帮助的。 - 错误消息的倒数第二行告诉我们错误发生在哪一行。这有助于我们追踪错误。在上面的例子中,
TypeError
发生在line 1
。
必答题
Python 会显示什么?
问题1:控制
使用 Ok 通过下面的“Python 会显示什么?”来测试您的知识。问题:
python3 ok -q control -u
提示:确保您的
while
循环条件最终求值为假,否则它们永远不会停止!键入Ctrl-C
将停止解释器中的无限循环。
>>> def xk(c, d):
... if c == 4:
... return 6
... elif d >= 4:
... return 6 + 7 + c
... else:
... return 25
>>> xk(10, 10)
______
>>> xk(10, 6)
______
>>> xk(4, 6)
______
>>> xk(0, 0)
______
>>> def how_big(x):
... if x > 10:
... print('huge')
... elif x > 5:
... return 'big'
... elif x > 0:
... print('small')
... else:
... print("nothing")
>>> how_big(7)
______
>>> how_big(12)
______
>>> how_big(1)
______
>>> how_big(-1)
______
>>> n = 3
>>> while n >= 0:
... n -= 1
... print(n)
______
提示:确保您的
while
循环条件最终评估为假值,否则它们永远不会停止!键入Ctrl-C
将停止解释器中的无限循环。
>>> positive = 28
>>> while positive:
... print("positive?")
... positive -= 3
______
>>> positive = -9
>>> negative = -12
>>> while negative:
... if positive:
... print(negative)
... positive += 3
... negative += 3
______
问题2:真值
使用 Ok 通过下面的“Python 会显示什么?”来测试您的知识。问题:
python3 ok -q short-circuit -u
>>> True and 13
______
>>> False or 0
______
>>> not 10
______
>>> not None
______
>>> True and 1 / 0 and False
______
>>> True or 1 / 0 or False
______
>>> True and 0
______
>>> False or 1
______
>>> 1 and 3 and 6 and 10 and 15
______
>>> -1 and 1 > 0
______
>>> 0 or False or 2 or 1 / 0
______
>>> not 0
______
>>> (1 + 1) and 1
______
>>> 1/0 or True
______
>>> (True or False) and False
______
问题3:调试测验
以下是有关不同调试技术的快速测验,将有助于您在本课程中使用。可以参考 调试 这篇文章回答问题。
使用 Ok 测试您的理解:
python3 ok -q debugging-quiz -u
编程练习
问题4:递降阶乘
让我们编写一个函数falling
,它是一个“递降”阶乘,接受两个参数n
和k
,并返回k
个连续数字的乘积,数字从n
开始并向下走。当k
为 0 时,函数应返回 1。
def falling(n, k):
"""Compute the falling factorial of n to depth k.
>>> falling(6, 3) # 6 * 5 * 4
120
>>> falling(4, 3) # 4 * 3 * 2
24
>>> falling(4, 1) # 4
4
>>> falling(4, 0)
1
"""
"*** YOUR CODE HERE ***"
使用 Ok 测试您的代码:
python3 ok -q falling
问题5:数字求和
编写一个函数,接收一个非负整数并将其各位数字相加。(这里使用整除和取模可能会有所帮助!)
def sum_digits(y):
"""Sum all the digits of y.
>>> sum_digits(10) # 1 + 0 = 1
1
>>> sum_digits(4224) # 4 + 2 + 2 + 4 = 12
12
>>> sum_digits(1234567890)
45
>>> a = sum_digits(123) # make sure that you are using return rather than print
>>> a
6
"""
"*** YOUR CODE HERE ***"
使用 Ok 测试您的代码:
python3 ok -q sum_digits
提交
确保通过运行以下命令提交此作业:
python3 ok --submit
提醒:请填写 实验 0 安装调查(也包含在本作业的开头):此处。
额外练习
这些问题是可选的,不会影响您在此作业中的分数。但是,它们是未来作业、项目和考试的绝佳练习。尝试这些问题有助于巩固您对课程概念的了解。
问题6:这会怎样?
使用 Ok 通过下面的“Python 会显示什么?”来测试您的知识。问题:
python3 ok -q if-statements -u
提示:
return
)并不会导致函数退出。
>>> def ab(c, d):
... if c > 5:
... print(c)
... elif c > 7:
... print(d)
... print('foo')
>>> ab(10, 20)
______
>>> def bake(cake, make):
... if cake == 0:
... cake = cake + 1
... print(cake)
... if cake == 1:
... print(make)
... else:
... return cake
... return make
>>> bake(0, 29)
______
>>> bake(1, "mashed potatoes")
______
问题7:数字88
编写一个函数,接收一个数字并确定这些数字是否包含两个相邻的 8。
def double_eights(n):
"""Return true if n has two eights in a row.
>>> double_eights(8)
False
>>> double_eights(88)
True
>>> double_eights(2882)
True
>>> double_eights(880088)
True
>>> double_eights(12345)
False
>>> double_eights(80808080)
False
"""
"*** YOUR CODE HERE ***"
使用 Ok 测试您的代码:
python3 ok -q double_eights
留言