习题 18: 命名、变量、代码、函数 ********************************************** 标题包含的内容够多的吧?接下来我要教你“函数(function)”了!咚咚锵!\ 说到函数,不一样的人会对它有不一样的理解和使用方法,不过我只会教你\ 现在能用到的最简单的使用方式。 函数可以做三样事情: 1. 它们给代码片段命名,就跟“变量”给字符串和数字命名一样。 2. 它们可以接受参数,就跟你的脚本接受 ``argv`` 一样。 3. 通过使用 #1 和 #2,它们可以让你创建“微型脚本”或者“小命令”。 你可以使用 ``def`` 新建函数。我将让你创建四个不同的函数,它们工作起来和你的\ 脚本一样。然后我会演示给你各个函数之间的关系。 .. literalinclude:: ex/ex18.py :linenos: 让我们把你一个函数 ``print_two`` 肢解一下,这个函数和你写脚本的方式差不多,\ 因此你看上去应该会觉着比较眼熟: 1. 首先我们告诉 Python 创建一个函数,我们使用到的命令是 ``def`` ,也就是\ “定义(define)”的意思。 2. 紧接着 ``def`` 的是函数的名称。本例中它的名称是 "print_two",但名字可以\ 随便取,就叫 "peanuts" 也没关系。但最好函数的名称能够体现出函数的功能来。 3. 然后我们告诉函数我们需要 ``*args`` (asterisk args),这和脚本的 ``argv`` 非常相似,参数必须放在圆括号 ``()`` 中才能正常工作。 4. 接着我们用冒号 ``:`` 结束本行,然后开始下一行缩进。 5. 冒号以下,使用 4 个空格缩进的行都是属于 ``print_two`` 这个函数的内容。 其中第一行的作用是将参数解包,这和脚本参数解包的原理差不多。 6. 为了演示它的工作原理,我们把解包后的每个参数都打印出来,这和我们在之前脚本\ 练习中所作的类似。 函数 ``print_two`` 的问题是:它并不是创建函数最简单的方法。在 Python 函数中我们\ 可以跳过整个参数解包的过程,直接使用 ``()`` 里边的名称作为变量名。这就是 ``print_two_again`` 实现的功能。 接下来的例子是 ``print_one`` ,它向你演示了函数如何接受单个参数。 最后一个例子是 ``print_none`` ,它向你演示了函数可以不接收任何参数。 .. warning:: 如果你不太能看懂上面的内容也别气馁。后面我们还有更多的练习向你展示\ 如何创建和使用函数。现在你只要把函数理解成“迷你脚本”就可以了。 你应该看到的结果 =================== 运行上面的脚本会看到如下结果: .. literalinclude:: ex/ex18.txt :language: console 你应该已经看出函数是怎样工作的了。注意到函数的用法和你以前见过的 ``exists``\、 ``open``\,以及别的“命令”有点类似了吧?其实我只是为了让你容易理解才叫它们“命令”, 它们的本质其实就是函数。也就是说,你也可以在自己的脚本中创建你自己的“命令”。 加分习题 ============ 为自己写一个\ ``函数注意事项``\以供后续参考。你可以写在一个索引卡片上随时阅读,\ 直到你记住所有的要点为止。注意事项如下: 1. 函数定义是以 ``def`` 开始的吗? 2. 函数名称是以字符和下划线 ``_`` 组成的吗? 3. 函数名称是不是紧跟着括号 ``(`` ? 4. 括号里是否包含参数?多个参数是否以逗号隔开? 5. 参数名称是否有重复?(不能使用重复的参数名) 6. 紧跟着参数的是不是括号和冒号 ``):`` ? 7. 紧跟着函数定义的代码是否使用了 4 个空格的缩进 (``indent``)? 8. 函数结束的位置是否取消了缩进 ("dedent")? 当你运行(或者说“使用 use”或者“调用 call”)一个函数时,记得检查下面的要点: 1. 调运函数时是否使用了函数的名称? 2. 函数名称是否紧跟着 ``(`` ? 3. 括号后有无参数?多个参数是否以逗号隔开? 4. 函数是否以 ``)`` 结尾? 按照这两份检查表里的内容检查你的练习,直到你不需要检查表为止。 最后,将下面这句话阅读几遍: “‘运行函数(run)’、‘调用函数(call)’、和 ‘使用函数(use)’是同一个意思” 常见问题回答 ========================== 函数名称有什么规则? 和变量名一样,只要以字母数字以及下划线组成,而且不是数字开始,就可以了。 ``*args`` 的 ``*`` 是什么意思? 它的功能是告诉 python 让它把函数的所有参数都接受进来,然后放到名字叫 args 的列表中去。\ 和你一直在用的 ``argv`` 差不多,只不过前者是用在函数上面。没什么特殊情况,我们一般不会\ 经常用到这个东西。 这些任务好枯燥好无聊啊。 这就对了,你这么感觉,说明你有了进步,你能明白代码的功用,而且写错代码的情况在你身上很少发生了。\ 为了让任务不那么无聊,你可以试着故意写错一些东西,看看会发生什么事情。