Python 解释器
Python 语言快速入门,为项目 4 用 Scheme 编写 Python 解释器做准备。
Python 简介
我们将学习 Python,也就是 CS61A 课程使用的语言。CS61A 的同学们正在用 Python 编写一个 Scheme 解释器。而在 CS61AS 这门课里,你的最后一个项目将是用 Scheme 写一个 Python 解释器(Python interpreter)。
打开 Python
要打开 Python,进入终端输入 “python”,随后会出现 ”>>>” 提示符,它相当于 Scheme 的 ”->”。
稍后你会发现,Python 中的空格非常重要。对 Python 而言,空格的地位相当于 Scheme 的圆括号。
玩转 Python
在解释器里试试下面这些命令。其中大部分来自项目说明文档,另外补充了一些例子。有些例子是故意会报错的。如果你遇到意料之外的行为,请提问!
怎么让 Python 打印 “Hello World” 呢?就这样:
>>> print "Hello World"
Hello World
就这样!(真的,没骗你)。从这个简单的例子你可能已经注意到,Python 调用函数不需要左圆括号,print 前面不需要加左括号。Python 区分大小写,所以 “PRINT” 不行。另一个关键区别是:Python 只支持中缀运算符,运算符位于其运算数之间:
>>> print 2 + 2
4
其实你不一定需要 print 语句;解释器会自动求值你在提示符下输入的任何内容,它使用一个读取-求值-打印循环(Read-Eval-Print loop),与元循环求值器所用的循环非常相似(再过两节我们会探讨它)。例如:
>>> 2 + 2
4
下面这些的输出是什么?
>>> 3 + 1 - 5 * 1
>>> 3 + (1 - 5) * 1
>>> 10/2
>>> 10/0
>>> (5+1)
>>> (10)
赋值
Python 中的赋值与其他语言类似。例如,如果你想把一个值赋给名为 x 的变量:
>>> x = 2
>>> print x
2
与 Scheme 不同,Python 不区分 DEFINE 和 SET!。如果变量 x 尚不存在,上述赋值就在全局环境中创建一个新变量 x;否则,x 的原有值会被覆盖。
试试下面这些:
>>> num
>>> num = 3
>>> num
>>> num = num + 1
>>> num
>>> num = "Berkeley"
>>> num
布尔值
「既然用 ”=” 赋值,那怎么判断相等呢?」Python(以及大多数其他语言)用 ”==” 代替。
试试下面这些:
>>> 5 == 1
>>> 5 == 5
>>> 5 = 5
>>> x = 10
>>> x == 5
>>> x == 10
>>> x == x
Python 支持布尔运算符 and 和 or,它们的行为与对应的 Scheme 特殊形式完全一致:
>>> x = 3
>>> (x == 3) and (x == 4)
False
>>> True and 3 and 5
5
>>> True and 3 and False
False
>>> True or 3 or False
True
Python 中对应 #t 和 #f 的分别是 True 和 False(大小写很重要)。
试试下面这些:
>>> True and True and False
>>> True and True and True
>>> (1 == 0) and (42 == 42)
>>> (1 == 1) and (42 == (1 / 0))
>>> (1 == 0) and (42 == (1 / 0))
>>> 2 and 3 and 4
>>> (1 == 0) or (42 == (1 / 0))
>>> (1 == 1) or (42 == (1 / 0))
>>> True or 5
>>> False or 5
>>> 5 or True
>>> 10 or 5
>>> False or (1 == 0) or 5
>>> not True
>>> not False
>>> not (1==0)
>>> not 5
>>> not "world"
>>> not ""
表
Python 有表(list)!(它怎么会没有呢?)
>>> x = [1, 2, 3]
现在 x 是一个存储着三个数的表的变量。你大概猜到了,它相当于 Scheme 里的 (list 1 2 3)。Python 的表也可以是嵌套的:
>>> x = [[1, 2, 3], 2, 3]
可惜,我们不能对 Python 的表用 CAR 或 CDR。要访问表中的特定元素:
>>> x[1]
2
记法 “x[1]” 返回表中的第二个元素(Python 使用从零开始的计数)。同样,这里可以把 ”[” 看作一个中缀运算符。
试试下面这些:
>>> [0,1,3,-1,5]
>>> lst = [0,1,3,-1,5]
>>> lst
>>> 0 in lst
>>> 4 in lst
>>> 0 not in lst
>>> 4 not in lst
>>> newlst = ["hey","I am", "a list", "too", ["boo", 100]]
>>> newlst
>>> "hey" in newlst
>>> "am" in newlst
>>> newlst[0]
>>> newlst[0] == "hey"
>>> newlst[1]
>>> newlst[4]
>>> newlst[5]
语句块
If 语句
Python 有一个重要特点,源于它对代码可读性的追求,那就是缩进(INDENTATION)的使用。在包括 Scheme 在内的大多数其他语言中,缩进无关紧要,因为这些语言不在乎有多少个空格,只用空格来分隔符号、数和单词。而在 Python 中,一行开头的空格数是重要的。
>>> x = 2
>>> if x == 1:
... x = x + 1
... print x
(在紧接着出现的 ”…” 提示符后,你需要再按一次 ENTER 键,表示 if 语句输入完毕。)Python 的 if 语句与 Scheme 中的对应形式工作原理相同:如果 if 语句的条件满足,就求值语句体。注意我们用了 ”==” 而不是 ”=“:因为 ”=” 已用于赋值,所以用 ”==” 判断相等。还要注意语句体是缩进的:语句体中的所有语句必须以相同的缩进开头。因此,下面这样是不行的:
>>> x = 2
>>> if x > 1:
... x = x + 1
... print x
因为语句体中的第二条语句比第一条缩进得更多。类似地,下面这样也不行:
>>> x = 2
>>> if x > 1:
... x = x + 1
... print x
因为语句体中的第二条语句比第一条缩进得更少。一般来说,只有当你结束一组相关语句(即一个语句块,BLOCK)时,才应该减少缩进(DEDENT)。一个语句块中的所有语句必须以相同数量的空格缩进。再举一个例子,if 语句还可以有 else 子句,当条件不满足时求值它。
>>> x = 2
>>> if x > 1:
... x = x + 1
... print x
... else:
... x = x - 1
... print x
注意,if 语句及其 else 子句对应语句块内部的行缩进量相同,但两个块本身的缩进量不同(虽然也可以相同!)。不过,if 语句和 else 子句的缩进量必须相同,因为它们属于同一条语句。然而,所有不属于语句块或子语句块的语句都不应有缩进。在 Python 解释器提示符下试试下面这条语句(它在 ”>>> ” 之后有两个空格的缩进):
>>> 2 + 3
缩进能强制写出整洁的代码,但可能需要一段时间才能习惯;关键是记住:只有开始一个新的语句块时才需要缩进。
试试下面这些:
>>> if x == 3:
... print x + 1
... elif x < 4:
... print x + 2
... elif x > 5:
... print x + 3
... else:
... print x + 4
定义函数
Python 也有函数(FUNCTIONS),它相当于 Scheme 的过程。下面定义了 square 函数:
>>> def square(x):
... return x * x
(同样,在紧接着出现的 ”…” 提示符后,你需要再按一次 ENTER 键,表示过程体输入完毕。)这个语法与 C 类语言相似:函数的实参写在函数名后面的圆括号里。调用函数:
>>> square(3)
9
从这个意义上说,左圆括号可以看作一个中缀运算符,运算符位于其运算数之间。要理解这一点,回忆一下:在 Scheme 中,左圆括号可以看作前缀运算符,它把第一个实参「调用」在后续实参上。类似地,在 Python 中,左圆括号把第一个实参(square)「调用」在下一个实参(3)上。另外,如果 Python 过程需要返回值,我们必须在函数体中显式添加 return 语句来返回结果;相比之下,在 Scheme 中,过程定义的最后一行总是被返回。这让我们可以区分两类 Python 函数:一类返回值,另一类不返回值、主要用于其副作用:
>>> def foo():
... print "Hello World"
试试下面这些:
>>> def sum_of_squares(x,y):
... return square(x) + square(y)
>>> sum_of_squares(3,4)
>>> square(square(2))
循环
Python 有循环结构。项目说明文档中有更详细的解释,但先试试下面这些代码:
while
while 循环接受一个谓词,只要谓词求值为 False,就会继续求值循环体。
>>> x = 3
>>> while x < 5:
... print x
... x = x + 1
>>> y = 1
>>> while y < 50:
... print y
... y = y*2
for
for 循环接受一个表(或任何序列),用序列中的每个元素依次执行循环体。这类似于你在第 9 课学过的循环。
>>> for i in [1, 3, 5, 2, 4]:
... print i
>>> for wd in ["Twinkle","twinkle","little","stars"]:
... print wd