当需要在程序中多次执行同一项任务时,无须反复编写完成该任务的代码,只需要调用执行该任务的函数,让 Python 运行其中的代码即可。你将发现,使用函数,程序编写、阅读、测试和修复起来都会更容易。
括号必不可少。示例的函数比较简单,不需要任何额外信息就能完成工作,因此括号内是空的。
Python 在为程序中的函数生成文档时,会查找紧跟在函数定义后的字符串注释。文档字符串通常前后分别用三个双引号引起,能够包含多行。
括号必不可少。示例的函数比较简单,不需要任何额外信息就能完成工作,因此括号内是空的。
示例中,我们将实参 'jesse' 传递给函数 greet_user(),这个值被赋给了形参 username。
大家有时候会形参、实参不分,即便你遇到了也不要大惊小怪,下面展示一种形象的记忆法。
记忆实参和形参的形象记忆法,简单介绍记忆
书中单词 hamster 的意思是仓鼠,这里改为了熟知的单词 cat
在这个函数调用中,先指定名字,再指定动物类型。由于实参 'harry' 在前,这个值将被赋给形参 animal_type,而后面的 'cat' 将被赋给形参 pet_name。结果是有一个名为 Cat 的 harry
使用哪种调用方式无关紧要。可以使用对你来说最容易理解的调用方式,只要函数调用能生成你期望的输出就好。
traceback 首先指出问题出在什么地方(见 1),让我们能够回过头去找出函数调用中的错误。
然后,指出导致问题的函数调用(见 2)。
最后,traceback 指出该函数调用缺少两个实参,并指出了相应形参的名称(见 3)
如果这个函数存储在一个独立的文件中,我们也许无须打开这个文件并查看函数的代码,就能重新正确地编写函数调用。
(本页为增补)
为了让函数在没有提供中间名时依然正确运行,可给形参 middle_name 指定默认值(空字符串),并将其移到形参列表的末尾(可选参数必须放在必选参数的后面),见 1。
在 2 处,通过 if 语句来判断是否提供了中间名,如果提供了,就将名、中间名和姓合并来生成姓名,反之则只使用名和姓来生成姓名,然后将姓名修改为首字母大写的格式,最后将结果返回函数调用行。
在 3 处,我们写了两种调用方式,第一种没有中间名,第二种则传入了中间名。
可选值在让函数能够处理各种不同情形的同时,确保函数调用尽可能简单。
(为了避免混淆,更推荐使用关键字实参的调用方式,这里限于版面未使用)
函数接受名和姓,并将这些值放在字典中(见 1)。
在存储 first_name 的值时,使用的键为 'first',而在存储 last_name 的值时,使用的键为 'last'。
然后,返回表示人的整个字典(见 2)。在 3 处,打印这个被返回的值。
在条件测试中,None 相当于 False。
在这个示例中,使用的是get_formatted_name()的简单版本,不涉及中间名。
while 循环让用户输入姓名:提示用户依次输入名和姓,随后打印出更为正规的问候语。
我们要让用户能够尽可能容易地退出,因此在每次提示用户输入时,都应提供退出途径。使用 break 语句可以在每次提示用户输入时退出循环
【Note】为了节省版面,减少冗余的介绍,这里忆及原书中与本节例子几乎完全相似的代码来做演示
第一个是 verify_users 函数,它的定义中包含两个形参,未验证用户列表和已验证用户列表,功能即验证每个用户,并将他们从未验证用户列表移入已验证用户列表。
第二个是 show_verified_users 函数,它的定义中包含一个形参,用于打印已验证用户列表中的用户信息。
D.R.Y: Don't repeat yourself
单一职责原则
除非有充分的理由,否则还是应该将原始列表传递给函数。
这是因为,让函数使用现成的列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。
函数体调用函数生成的输出,证明此时 Python 能够处理使用一个值调用函数的情形,也能处理使用三个值调用函数的情形。并且能知道,print() 函数是能够处理元组的。
注意运行结果的第一行,这是 Python 中仅有一个元素的元组写法(想想为什么这么写?)
Python 先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中。
你经常会看到通用形参名 *args,它也这样收集任意数量的位置实参。
在函数体内,我们将名和姓加入字典 user_info,因为总是会从用户那里收到这两项信息,而这两项信息还没被放在字典中。接下来,将字典 user_info 返回函数调用行,这个字典实际上是 Python 为我们创建的。
注意:你经常会看到形参名 **kwargs,它用于收集任意数量的关键字实参。
通过将函数存储在独立的文件中,可隐藏程序代码的细节,将重点放在程序的高层逻辑上。这还能让你在众多不同的程序中复用函数。将函数存储在独立文件中后,可与其他程序员共享这些文件而不是整个程序。知道如何导入函数还能让你使用其他程序员编写的函数库。
当 Python 读取这个文件时,代码行 import pizza 会让 Python 打开文件 pizza.py,并将其中的所有函数都复制到这个程序中。
你看不到复制代码的过程,因为 Python 会在程序即将运行时在幕后复制这些代码。你只需要知道,在 making_pizzas.py 中,可通过导入的模块,使用pizza.py 中定义的所有函数。
由于在 import 语句中显式地导入了 make_pizza()函数,因此在调用时只需指定其名称即可。
import 语句将函数 make_pizza() 重命名为 mp()。
在这个程序中,每当需要调用 pizza 模块的 make_pizza() 时,都需要使用其别名 mp()。
Python 将运行 pizza 模块中 make_pizza() 中的代码,同时避免与程序可能包含的 make_pizza()函数混淆。
上述import 语句给 pizza 模块指定了别名 p,但该模块中所有函数的名称都没变。
要调用 make_pizza() 函数,需要将其写为 p.make_pizza() 而不是 pizza.make_pizza()。
星号实际在这里充当通配符
描述性名称可帮助你和别人明白代码想要做什么。
文档字符串帮助别人了解函数的相关信息,让别人只需阅读其中的描述就能够使用它:他们完全可以相信代码会如描述的那样运行,并且只要知道函数名、需要的实参以及返回值的类型,就能在自己的程序中使用它。
PEP 8 建议代码行的长度不要超过79 个字符。
强调一下,如果是零基础入门,可选拓展是完全可以忽略的,要避免陷入知识的泥潭哦 。
题外话,原本打算在可选拓展中写上 “学习 Python 作用域规则(LEGB)”的,而不是“初步了解 Python 的作用域……”,但考虑到本书的入门性质,还是选择了后者的表述,因为类似的知识点即便是有经验的程序员,学习时也很容易被绕晕。
当然了,如果你想要成为 Python 专家,那么阅读进阶书籍(例如《流畅的 Python》等),就是你职业发展中必不可少的一环了。