实验1: 变量和函数,控制结构
Lab 1: Variables & Functions, Control
Due by 11:59pm on Tuesday, September 1.
查看英文原文
初始文件
下载 lab01.zip。 在压缩包中,你会找到本实验问题的初始文件, 以及一份 Ok 自动评分器。
另外,请填写 这份调查问卷,告知我们你在实验0中遇到的任何问题,或者你是否使用了Windows自动安装程序。
为了快速生成ok命令,你现在可以使用 ok命令生成器。
快速检查
使用 Python
在运行Python文件时,你可以使用命令行选项进一步检查你的代码。 以下是一些有用的选项。 如果你想了解更多关于其他Python命令行选项的信息,可以查看 此文档。
-
不使用任何命令行选项:这将运行你提供的文件中的代码,并返回到命令行。
python3 foo.py
-
-i
:-i
选项会运行你的 Python 脚本,然后打开一个交互式会话。 在交互式会话中,你可以逐行运行 Python 代码,并实时得到结果,而不是一次性运行整个文件。 你可以输入exit()
来退出。也可以使用 Linux/Mac 系统中的快捷键Ctrl-D
或者 Windows 系统中的Ctrl-Z Enter
来退出。如果在交互模式下运行 Python 文件时编辑了文件,你需要退出并重新启动解释器,才能让更改生效。
python3 -i foo.py
-
-m doctest
:在特定文件中运行doctests。 doctests可用于测试函数中用三引号("""
)包裹的测试样例。文件中的每个测试都由
>>>
开头, 后跟一些 Python 代码和预期的输出(不过>>>
不会出现在 doctest 命令的输出中)。python3 -m doctest foo.py
使用OK
在 CS61A 课程中,我们使用 Ok 来对实验、作业和项目进行自动评分。在本实验的初始文件中,你应该已经下载了 Ok。要了解更多关于 Ok 命令的使用信息,请点击这里.
你可以在 links.cs61a.org/ok-help 快速生成大多数 Ok 命令!
要使用 Ok 运行指定函数的 doctest,请运行以下命令:
python3 ok -q <指定函数名> --local
默认情况下,只有未通过的测试会显示出来。你可以使用 -v
选项来查看所有测试,包括你已通过的测试:
python3 ok -v
你还可以在 Ok 中使用调试打印功能,方法如下:
print("DEBUG:", x)
最后,当你完成了
lab01.py 中的所有问题后,必须使用
--submit
选项提交作业:
python3 ok --submit
要了解更多 Ok 命令,请访问这里.
主要内容
如果你需要复习本实验的内容,请参考这一部分。你也可以直接跳到问题部分,遇到困难时再回来看这里。
Division
Let's compare the different division-related operators in Python 3:
True Division: / (decimal division) |
Floor Division: // (integer division) |
Modulo: % (remainder) |
---|---|---|
|
|
|
Notice that Python outputs ZeroDivisionError
for certain cases. We will go over this later in
this lab under Error Messages.
One useful technique involving the %
operator is to check
whether a number x
is divisible by another number y
:
x % y == 0
For example, in order to check if x
is an even number:
x % 2 == 0
Functions
If we want to execute a series of statements over and over, we can abstract them away into a function to avoid repeating code.
For example, let's say we want to know the results of multiplying the numbers 1-3 by 3 and then adding 2 to it. Here's one way to do it:
>>> 1 * 3 + 2
5
>>> 2 * 3 + 2
8
>>> 3 * 3 + 2
11
If we wanted to do this with a larger set of numbers, that'd be a lot of repeated code! Let's write a function to capture this operation given any input number.
def foo(x):
return x * 3 + 2
This function, called foo
, takes in a single argument and will
return the
result of multiplying that argument by 3 and adding 2.
Now we can call this function whenever we want this operation to be done:
>>> foo(1)
5
>>> foo(2)
8
>>> foo(1000)
3002
Applying a function to some arguments is done with a call expression.
Call expressions
A call expression applies a function, which may or may not accept arguments. The call expression evaluates to the function's return value.
The syntax of a function call:
add ( 2 , 3 )
| | |
operator operand operand
Every call expression requires a set of parentheses delimiting its comma-separated operands.
To evaluate a function call:
- Evaluate the operator, and then the operands (from left to right).
- Apply the operator to the operands (the values of the operands).
If an operand is a nested call expression, then these two steps are applied to that inner operand first in order to evaluate the outer operand.
return
and print
Most functions that you define will contain a return
statement. The return
statement will give the result of some computation back to the caller of the
function and exit the function. For example, the function square
below takes
in a number x
and returns its square.
def square(x):
"""
>>> square(4)
16
"""
return x * x
When Python executes a return
statement, the function terminates immediately.
If Python reaches the end of the function body without executing a return
statement, it will automatically return None
.
In contrast, the print
function is used to display values in the Terminal.
This can lead to some confusion between print
and return
because calling a
function in the Python interpreter will print out the function's return value.
However, unlike a return
statement, when Python evaluates a print
expression, the function does not terminate immediately.
def what_prints():
print('Hello World!')
return 'Exiting this function.'
print('61A is awesome!')
>>> what_prints()
Hello World!
'Exiting this function.'
Notice also that
return
will preserve the quotes.
Control
Boolean Operators
Python supports three boolean operators: and
, or
, and not
:
>>> a = 4
>>> a < 2 and a > 0
False
>>> a < 2 or a > 0
True
>>> not (a > 0)
False
and
evaluates toTrue
only if both operands evaluate toTrue
. If at least one operand isFalse
, thenand
evaluates toFalse
.or
evaluates toTrue
if at least one operand evaluates toTrue
. If both operands areFalse
, thenor
evaluates toFalse
.not
evaluates toTrue
if its operand evaluates toFalse
. It evaluates toFalse
if its operand evalutes toTrue
.
What do you think the following expression evaluates to? Try it out in the Python interpreter.
>>> True and not False or not True and False
It is difficult to read complex expressions, like the one above, and understand how a program will behave. Using parentheses can make your code easier to understand. Python interprets that expression in the following way:
>>> (True and (not False)) or ((not True) and False)
This is because boolean operators, like arithmetic operators, have an order of operation:
not
has the highest priorityand
or
has the lowest priority
Truthy and Falsey Values: It turns out and
and or
work on more
than just booleans (True
,
False
). Python values such as 0
, None
, ''
(the
empty string), and []
(the empty list) are considered false values. All other values are considered
true values.
Short Circuiting
What do you think will happen if we type the following into Python?
1 / 0
Try it out in Python! You should see a ZeroDivisionError
. But what about this expression?
True or 1 / 0
It evaluates to True
because Python's and
and or
operators
short-circuit. That is, they don't necessarily evaluate every operand.
Operator | Checks if: | Evaluates from left to right up to: | Example |
---|---|---|---|
AND | All values are true | The first false value | False and 1 / 0 evaluates to False |
OR | At least one value is true | The first true value | True or 1 / 0 evaluates to True |
Short-circuiting happens when the operator reaches an operand that allows them to make a conclusion about
the expression. For example, and
will short-circuit as soon as it reaches the first false value
because it then knows that not all the values are true.
If and
and or
do not short-circuit, they just return the last
value; another way to remember this is that and
and or
always return the last
thing they evaluate, whether they short circuit or not. Keep in mind that and
and
or
don't always return booleans when using values other than True
and False
.
If Statements
You can review the syntax of if
statements in
Section 1.5.4
of Composing Programs.
Tip: We sometimes see code that looks like this:
if x > 3: return True else: return False
This can be written more concisely as
return x > 3
. If your code looks like the code above, see if you can rewrite it more clearly!
While Loops
You can review the syntax of while
loops in
Section 1.5.5
of Composing Programs.
Error Messages
By now, you've probably seen a couple of error messages. They might look intimidating, but error messages are very helpful for debugging code. The following are some common types of errors:
Error Types | Descriptions |
---|---|
SyntaxError | Contained improper syntax (e.g. missing a colon after an if statement or
forgetting to close parentheses/quotes) |
IndentationError | Contained improper indentation (e.g. inconsistent indentation of a function body) |
TypeError | Attempted operation on incompatible types (e.g. trying to add a function and a number) or called function with the wrong number of arguments |
ZeroDivisionError | Attempted division by zero |
Using these descriptions of error messages, you should be able to get a better idea of what went wrong with your code. If you run into error messages, try to identify the problem before asking for help. You can often Google unfamiliar error messages to see if others have made similar mistakes to help you debug.
For example:
>>> square(3, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: square() takes 1 positional argument but 2 were given
Note:
- The last line of an error message tells us the type of the error. In the
example above, we have a
TypeError
. - The error message tells us what we did wrong -- we gave
square
2 arguments when it can only take in 1 argument. In general, the last line is the most helpful. -
The second to last line of the error message tells us on which line the error occurred. This helps us track down the error. In the example above,
TypeError
occurred atline 1
.
必答题
Python会输出什么? (Part 1)
Q1: WWPD: 控制
使用 Ok 的 "Python会输出什么?" 的题目来测试你的学习成果:
python3 ok -q control -u --local
提示: 确保你的
while
循环的判断条件最终为 False ,不然你的程序将进入死循环。 按Ctrl-C
来停止
>>> def xk(c, d):
... if c == 4:
... return 6
... elif d >= 4:
... return 6 + 7 + c
... else:
... return 25
>>> xk(10, 10)
______23
>>> xk(10, 6)
______23
>>> xk(4, 6)
______6
>>> xk(0, 0)
______25
>>> def how_big(x):
... if x > 10:
... print('huge')
... elif x > 5:
... return 'big'
... elif x > 0:
... print('small')
... else:
... print("nothin")
>>> how_big(7)
______'big'
>>> how_big(12)
______huge
>>> how_big(1)
______small
>>> how_big(-1)
______nothin
>>> n = 3
>>> while n >= 0:
... n -= 1
... print(n)
______2
1
0
-1
>>> positive = 28
>>> while positive:
... print("positive?")
... positive -= 3
______Infinite Loop
>>> positive = -9
>>> negative = -12
>>> while negative:
... if positive:
... print(negative)
... positive += 3
... negative += 3
______-12
-9
-6
Q2: WWPD: 值的真假
使用 Ok 的 "Python会输出什么?" 的题目来测试你的学习成果:
python3 ok -q short-circuit -u --local
>>> True and 13
______13
>>> False or 0
______0
>>> not 10
______False
>>> not None
______True
>>> True and 1 / 0 and False
______Error (ZeroDivisionError)
>>> True or 1 / 0 or False
______True
>>> True and 0
______0
>>> False or 1
______1
>>> 1 and 3 and 6 and 10 and 15
______15
>>> -1 and 1 > 0
______True
>>> 0 or False or 2 or 1 / 0
______2
>>> not 0
______True
>>> (1 + 1) and 1
______1
>>> 1/0 or True
______Error
>>> (True or False) and False
______False
Q3: 调试测验!
以下是一个关于本课程中应使用的不同调试技巧的快速测验。你应该参考此文档来回答问题!
运行以下命令开始测验:
python3 ok -q debugging-quiz -u --local
编程练习
Q4: 递减阶乘
让我们编写一个函数 falling
,
它是一个“递减”阶乘函数,接受两个参数 n
和 k
,并返回从 n
开始,向下递减的 k
个连续数字的乘积。
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 --local
Q5: 数位之和
编写一个函数,该函数接受一个非负整数并计算其各位数字的和。(使用取整除法和取模运算可能会对你有帮助!)
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 --local
Submit
Make sure to submit this assignment by running:
python3 ok --submit
Reminder: Please fill out the Lab 0 survey (also included at the beginning of this assignment): this survey
扩展练习
这些问题是可选的,不会影响你在本次作业中的分数。 然而,它们对于未来的作业、项目和考试是很好的练习。 尝试这些问题对巩固你对课程概念和理解非常有帮助,而且它们很有趣!
Python会输出什么?(Part 2)
Q6: WWPD: 条件判断
使用 Ok 的"Python会输出什么?"的题目来测试你的学习成果:
python3 ok -q if-statements -u --local
提示:
return
不同) 不会导致函数退出!
>>> def ab(c, d):
... if c > 5:
... print(c)
... elif c > 7:
... print(d)
... print('foo')
>>> ab(10, 20)
______10
foo
>>> 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)
______1
29
29
>>> bake(1, "mashed potatoes")
______mashed potatoes
'mashed potatoes'
扩展编程练习
Q7: 双8
编写一个函数,该函数接受一个数字,并判断其数字中是否包含两个相邻的 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 --local