习题 25: 更多更多的练习 ******************************* 我们将做一些关于函数和变量的练习,以确认你真正掌握了这些知识。这节练习对你来说\ 可以说是一本道:写程序,逐行研究,弄懂它。 不过这节练习还是有些不同,你不需要运行它,取而代之,你需要将它导入到 python 里\ 通过自己执行函数的方式运行。 .. literalinclude:: ex/ex25.py :linenos: 首先以正常的方式 ``python ex25.py`` 运行,找出里边的错误,并把它们都改正过来。\ 然后你需要接着下面的答案章节完成这节练习。 你应该看到的结果 =================== 这节练习我们将在你之前用来做算术的 ``python`` 编译器里,用交互的方式和你的\ ``.py`` 作交流。 这是我做出来的样子: .. literalinclude:: ex/ex25.txt :linenos: :language: pycon 我们来逐行分析一下每一步实现的是什么: * 在第 5 行你将自己的 ``ex25.py`` 执行了 import,和你做过的其它 import 一样。在 import 的时候\ 你不需要加 ``.py`` 后缀。这个过程里,你把 ``ex25.py`` 当做了一个“模组(module)”来使\ 用,你在这个模组里定义的函数也可以直接调用出来。 * 第 6 行你创建了一个用来处理的“句子(sentence)”。 * 第 7 行你使用 ``ex25`` 调用你的第一个函数 ``ex25.break_words``\。其中的 ``.`` (dot, period)符号可以告诉 Python:“嗨,我要运行 ``ex25`` 里的哪个个叫 ``break_words`` 的函数!” * 第 8 行我们只是输入 ``words``\,而 python 将在第 9 行打印出这个变量里边有什么。看上去可能\ 会觉得奇怪,不过这其实是一个“列表(list)”,你会在后面的章节中学到它。 * 10-11 行我们使用 ``ex25.sort_words`` 来得到一个排序过的句子。 * 13-16 行我们使用 ``ex25.print_first_word`` 和 ``ex25.print_last_word`` 将第一个和最后一个词\ 打印出来。 * 第 17 行比较有趣。我把 ``words`` 变量写错成了 ``wrods``\,所以 python 在 18-20 行给了一个错误信息。 * 21-22 行我们打印出了修改过的词汇列表。第一个和最后一个单词我们已经打印过了,所以在这里\ 没有再次打印出来。 剩下的行你需要自己分析一下,就留作你的加分习题了。 加分习题 ============ 1. 研究答案中没有分析过的行,找出它们的来龙去脉。确认自己明白了自己使用的是模组 ``ex25`` 中\ 定义的函数。 2. 试着执行 ``help(ex25)`` 和 ``help(ex25.break_words)`` 。这是你得到模组帮助文档的方式。 所谓帮助文档就是你定义函数时放在 ``"""`` 之间的东西,它们也被称作 ``documentation comments`` (文档注解),后面你还会看到更多类似的东西。 3. 重复键入 ``ex25.`` 是很烦的一件事情。有一个捷径就是用 ``from ex25 import *`` 的方式\ 导入模组。这相当于说:“我要把 ex25 中所有的东西 import 进来。”程序员喜欢说这样的倒装句,\ 开一个新的会话,看看你所有的函数是不是已经在那里了。 4. 把你脚本里的内容逐行通过 ``python`` 编译器执行,看看会是什么样子。你可以执行\ CTRL-D (Windows 下是 CTRL-Z)来关闭编译器。 常见问题回答 ========================== 有的函数打印出来的结果是 ``None`` 。 也许你的函数漏写了最后的 ``return`` 语句。回到代码中检查一下是不是每一行都写对了。 输入 ``import ex15`` 时显示 ``-bash: import: command not found`` 。 注意看《你应该看到的结果》部分。我是在 Python 中写的这句,不是在命令行终端直接写的。你要\ 先运行 python 再输入代码。 输入 ``import ex25.py`` 时显示 ``ImportError: No module named ex25.py`` 。 ``.py`` 是不需要的。Python z知道文件是 ``.py`` 结尾,所以只要输入 ``import ex25`` 即可。 运行时提示 ``SyntaxError: invalid syntax`` 。 这说明你在提示的那行有一个语法错误,可能是漏了半个括号或者引号,也可能识别的。一旦看到这种\ 错误,你应该去对应的行检查你的代码,如果这行没问题,就倒着继续往上检查每一行,直到发现问题为止。 函数里的代码不是只在函数里有效吗?为什么 ``words.pop(0)`` 这个函数会改变 words 的内容? 这个问题有点复杂,不过在这里 ``words`` 是一个列表,你可以对它进行操作,操作结果也可以\ 被保存下来。这和你操作文件时文件的 ``f.readline()`` 工作原理差不多。 函数里什么时候该用 ``print`` ,什么时候该用 ``return`` ? ``print`` 只是屏幕输出而已,你可以让一个函数既 ``print`` 又返回值。当你明白这一点后,\ 你就知道这个问题其实没什么意义。如果你想要打印到屏幕,那就使用 ``print`` ,如果是想返回\ 值,那就是用 ``return`` 。.