是时候自己开始编程了。这一部分的练习相当简单,但是这样是为了确保你为学习钻研本书的剩余部分做好准备,而这里的一些问题提示了未来章节的一些主题。一定要查看附录D的第一部分以获取答案(我抄就是了);练习题以及解答有时候包含了·一些并没有在这部分主要内容中的补充信息,所以即使你能够独立回答所有问题,也应该看看解答。
1.交互使用系统命令行,IDLE或者任何你的平台上工作的其他方法,开始Python交互命令行(>>>提示符),并输入表达式"Hello World!"(包括引号)(注意符号都是英文的)。这行字符串将会显示出来。这个练习的目的是确保已配置Python运行的环境。在某些情况下,你也许需要首先运行一条shell命令,输入Python可执行文件的绝对路径,或者增加Python可执行文件的路径至PATH环境变量。如果想要的话,你可以在.cshrs或.kshrc文件中设置PATH,使Python在UNIX系统中永久可用:在Windows上,环境变量GUI通常就是你想要的。参照附录A获得环境变量设置的帮(有空我拍张照片的吧)。
假设Python以被正确配置,交互模式看起来应该想下面这样(可用在IDLE、shell命令行或其他方式下运行):
2.程序。使用你选择的文本编辑器,写一个简单的包含了单个打印‘Hello module world!’语句的模块文件,并将其保存为module1.py。现在,通过使用任何你喜欢的去的选项来运行这个文件:在IDLE中运行,点击文件图标,在系统shell的命令行中将其传递给Python解释器程序(例如python module.py)等,实际上,尽可能地使用本章所讨论到的启动技术运行你的文件去实验。哪种技术看起来更简单?(当然,这个问题没有正确的答案)
你的程序代码(模块)文件module1.py和操作系统的shell的交互应该看起来像下面这样:
同样,你也可以用其他方式运行:单机文件图标,使用IDLE的RUN RUN Module 菜单选项等。
3.模块。紧接着,开始一个Python交互命令行(>>>提示符),并导入你在练习2中所写的模块,试着将这个文件移动到一个不同的目录,并在此从其原始的目录导入(也就是说,当导入时在原来那个目录运行Python)。发生了什么?(提示:在原来的目录中是否仍然有一个module1.pyc的字节码文件,或者在__pycache__子目录下有类似的文件?)
下面的交互结果说明了应该如何导入模块文件从而运行一个模块:
要记住,如果你不想停止和重启解释器的情况下再次运行一个模块,则需要重新加载它。把文件移动到不同的目录并导入它是一个很有技巧性的问题:如果Python在最初的目录产生了module1.pyc文件,即代表源代码文件(.py)已被移植到不在Python搜索路径中的目录,在最初的目录中再次导入该模块时,Python依然会使用这个pyc文件。如果把当前目录切换到Python可读取源代码文件的目录,那么Python就会自动写.pyc文件。.pyc是模块编译后的字节码版本。参考第三章有关模块的内容。
4.脚本。如果你的平台支持的话,在module1.py模块文件的顶行增加一行#!,赋予这个文件的可执行的权限,并作为可执行文件直接运行它。在第一行需要包含什么?#!一般是UNIX、Linux和UNIX类平台(如Mac OS X)有意义,如果你在Windows平台上工作,遇过‘开始 到 运行’对话框或类似的操作,然后试着在命令行窗口不在其前边加‘python’这个词而直接列出其名字来运行这个文件(这在最新版本的Windows上有效)。如果你正在使用随着操作系统安装的Python3.3或Windows启动器,改变脚本的#!代码进行试验,来启动你可能在电脑上已安装的不同的Python版本。
假设你的平台支持#!技巧,你的解法看起来应该像下面这样(#!后面应该写东西的),虽然你的#!行可能需要列出机器上的另一路径。注意这些行对随着Python3.3配备和安装的Windows启动器是十分重要的,在启动器下它们被解析以选择Python的另一个版本来运行脚本,并带有默认设置:参看附录B获取更多细节和示例。
5.错误和调试。在Python交互命令行中,试着输入数学表达式和赋值。首先输入2**500和1/0,并且像我们在本章前面所做的那样引用一个未知的变量名。发生了什么?
你也许还不知道,但是当你翻了一个错误,你正在做的是异常处理:这将会在第七部分深入探索。如同你将会在那里学到的,从技术上正在触发所谓的默认打印本章错误信息的异常处理逻辑。如果你没有获得错误信息,那么默认的处理模块获得并作为回应打印了标准的错误信息。
异常总是和Python中的调试概念密切相关的。当你第一次开始的时候,Python关于异常的默认错误信息总是为你的错误处理提供尽可能多的支持,他们给出错误的原因,并且在代码中显示错误发生时所执行的行。要了解关于调试的更多内容,详见第三章的调试Python代码部分。
下面的交互模式示范了当你完成此练习题时会碰到的出错消息种类。其实,你只是触发了Python的异常;默认的异常处理行为会终止正在运行的Python程序,然后在屏幕上打印出错消息和调用栈的跟踪信息。调用栈的跟踪信息显示出当异常发生时,程序所运行到的位置。在第十章和第七部分中,你还可以使用try语句捕获它,并进行任意的处理。你也会看到Python包含了一套成熟的源代码调试器,从而可以满足特殊的错误检测的需求。就目前而言,程序错误发生时,Python会提供有意义的消息而不是默默地就崩溃了:
6.中断。在Python命令行中,输入:
L = [1,2]
L.append(L)
L
发生了什么,如果使用的是比1.5版本(我没写错)更新的Python,你也许能够看到一个奇怪的说辞,我们将会在本书的下一部分降到。如果你用的Python版本比1.5.1还老,在绝大多数平台上Ctrl+ C组合键也许会有用。为什么会发什么这种情况。
当你输入一下代码的时候:
L = [1,2]
L.append(L)
会在Python中创建循环数据结构。在1.5.1版以前,Python的打印不够智能,因此无法检测中对象中的循环,并会打印无止境的[1,2,[1,2,[1,2,[1,2,流,直到
你按下了机器上的中断组合键(从技术上来讲,这将引发键盘中断异常,并打印默认消息)。从Python1.5.1起,打印已经足够智能,可以检测出循环并打印[[...]],进而让你知道它已经在对象结构中检测到一个循环并避免永远打印。
这里出现的循环的原因很细节,并且需要用到本书第二部分中的内容,不过简而言之,Python中的赋值语句总是会产生对象的应用,而不是它们的副本。你可以把对象看做一快内存,把应用看做是隐式指向的指针。当你执行上面的第一条赋值语句时,名称L变成了一个指向双元素列表对象的引用名称,也就是指向一段内存的指针。Python的列表其实是对象引用的数组,它有一个append方法会通过在末尾添加另一个对象的引用,对数组进行原位置的修改。在这里,append调用会把L前面的引用加在L的末尾,从而造成下图所示的循环:列表末尾的一个指针指回到列表的头部。
正如第六章所学,循环对象不但会被特殊地打印,还必须被Python的垃圾回收器特殊处理,否则当它们不再使用时,将会出现空间仍旧未回收的情况。尽管这在实际中很少见,但在一些遍历任意对象或结构的程序中,你必须通过记录已经遍历到哪里,来检测并避免陷入这样的循环。不过尽管难以置信,但是循环数据结构偶尔也是很有用的(输入它的打印非常独特)。
7.文档。在你继续感受标准库中可用的工具和文档集的结构之前,至少话15分钟浏览一下Python库和语言手册,为了熟悉手册集的主题,至少得花这么长的时间。一旦你这样做了,将很容易找到你需要的东西。你可以在一些Windows版本上的Python开始按钮菜单选项,或者在IDLE的Help下拉菜单的Python Docs选项里,或者在网址http://www.python.org/doc上找到这个手册。本书将会在第15章用部分内容描述一些手册以及其他可用文档资源中的内容(包括PyDoc以及help函数)。如果还有时间,千万Python的网址以及PyPI第三方扩展的网站看看。特别留意Python.org(http://www.python.org)的文档和搜索界面,它们是至关重要的资源。