函数的创建和调用
提到函数,大家会想到数学函数,函数是数学最重要的一个模块,贯穿整个数学领域。在 Python 中,函数的应用也非常广泛。在前面已经多次接触过函数。例如,用于输出的 print()函数、用于输入的 input() 函数,以及用于生成一系列整数的 range() 函数,这些都是 Python 内置的标准函数,可以直接使用。除了可以直接使用的标准函数外, Python 还支持自定义函数,即通过将一段有规律的、重复的代码定义为函数,来达到一次编写多次调用的目的。使用函数可以提高代码的重复利用率。
创建函数
创建函数也称为定义函数,可以理解为创建一个具有某种用途的工具。使用 def 关键字实现创建函数,具体的语法格式如下:
def functionname([parameterlist]):
['''comments''']
[functionbody]参数说明如下:
- functionname :函数名称,在调用函数时使用。
- parameterlist :可选参数,用于指定向函数中传递的参数。如果有多个参数,各参数间使用逗号”,”进行分隔。如果不指定,则表示该函数没有参数,在调用时,也不指定参数。
注意:即使函数没有参数,也必须保留一对空的小括号”()”,否则将显示如下面所示的语法错误提示。
SyntaxError: invalid syntax
- ”’comments”’:可选参数,表示为函数指定注释,注释的内容通常是说明该函数的功能、要传递的参数的作用等,可以为用户提供友好提示和帮助的内容。
说明:在定义函数时,如果指定了 ”’comments”’ 参数,那么在调用函数时,输入函数名称及左侧的小括号时,就会显示该函数的帮助信息。这些帮助信息就是通过定义的注释提供的。
注意:如果在输入函数名和左侧括号后,没有显示友好提示,那么就检查函数本身是否有误,检查方法可以是在未调用该函数时,先按下快捷键<F5>执行一遍代码。
- functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。如果函数有返回值,可以使用 return 语句返回。
注意:函数体 “functionbody” 和注释 “”’comments”'” 相对于 def 关键字必须保持一定的缩进。
说明:如果想定义一个什么也不做的空函数,可以使用 pass 语句作为占位符。
调用函数
调用函数也就是执行函数。如果把创建函数理解为创建一个具有某种用途的工具,那么调用函数就相当于使用该工具。调用函数的基本语法格式如下:
functionname([parametersvalue])参数说明如下:
- functionname:函数名称,要调用的函数名称,必须是已经创建好的。
- parametersvalue:可选参数,用于指定各个参数的值。如果需要传递多个参数值,则各参数值间使用逗号 “,” 进行分隔。如果该函数没有参数,则直接写一对小括号即可。
参数传递
在调用函数时,在大多数情况下,主调用函数和被调用函数之间有数据传递关系,这就是有参数的函数形式。函数参数的作用是传递数据给函数使用,函数利用接收的数据进行具体的操作处理。
函数参数在定义函数时放在函数名称后面的一对小括号中,如图所示。
了解形式参数和实际参数
在使用函数时,经常会用到形式参数和实际参数,两者都叫作参数,两者之间的区别将先通过形式参数与实际参数的作用来进行讲解,再通过一个比喻进行深入理解。
1.通过作用理解
形式参数和实际参数在作用上的区别如下。
- 形式参数:在定义函数时,函数名后面括号中的参数为”形式参数”。
- 实际参数:在调用一个函数时,函数名后面括号中的参数为”实际参数”,也就是将函数的调用者提供给函数的参数称为实际参数。通过图8.5可以更好地理解。
根据实际参数的类型不同,可以分为将实际参数的值传递给形式参数,将实际参数的引用传递给形式参数两种情况。其中,当实际参数为不可变对象时,进行的是值传递;当实际参数为可变对象时,进行的是引用传递。实际上,值传递和引用传递的基本区别就是,进行值传递后,改变形式参数的值,实际参数的值不变;而进行引用传递后,改变形式参数的值,实际参数的值也一同改变。
在进行值传递时,改变形式参数的值后,实际参数的值不改变;在进行引用传递时,改变形式参数的值后,实际参数的值也发生改变。
2.通过一个比喻来理解形式参数和实际参数
函数定义时参数列表中的参数就是形式参数,而函数调用时传递进来的参数就是实际参数。
位置参数
位置参数也称为必备参数,必须按照正确的顺序传到函数中,即调用时的数量和位置必须和定义时是一样的。下面分别进行介绍。
1.数量必须与定义时一致
在调用函数时,指定的实际参数的数量必须与形式参数的数量一致,否则将抛出 TypeError 异常,提示缺少必要的位置参数。
例如,调用根据身高、体重计算 BMI 指数的函数 fun_bmi(person,height,weight),将参数少传一个,即只传递两个参数,代码如下:
fun_bmi("路人甲",1.83) #计算路人甲的 BMI 指数函数调用后,将显示异常信息。
从所示的异常信息中可以看出,抛出的异常类型为 TypeError ,具体的意思是” fun_bmi()方法缺少一个必要的位置参数 weight “。
2.位置必须与定义时一致
在调用函数时,指定的实际参数的位置必须与形式参数的位置一致,否则将产生以下两种结果。
(1)抛出 TypeError 异常
抛出异常的情况主要是因为实际参数的类型与形式参数的类型不一致,并且在函数中,这两种类型还不能正常转换。
例如,调用 fun_bmi (person,height,weight)函数,将第1个参数和第2个参数位置调换,代码如下:
fun_bmi(60,"路人甲",1.83) #计算路人甲的 BMI 指数函数调用后,将显示异常信息。主要是因为传递的整型数值不能与字符进行连接操作。
(2)产生的结果与预期不符
在调用函数时,如果指定的实际参数与形式参数的位置不一致,但是它们的数据类型一致,那么就不会抛出异常,但是产生的结果与预期不符。
例如,调用 fun_bmi (person,height,weight)函数,将第2个参数和第3个参数位置调换,代码如下:
fun_bmi("路人甲",60,1.83) #计算路人甲的 BMI 指数从结果中可以看出,虽然没有抛出异常,但是得到的结果与预期不符。
说明:由于调用函数时,传递的实际参数的位置与形式参数的位置不一致时,并不会总是抛出异常,所以在调用函数时一定要确定好位置,否则产生 Bug ,还不容易被发现。
关键字参数
关键字参数是指使用形式参数的名字来确定输入的参数值,通过该方式指定实际参数时,不再需要与形式参数的位置完全一致,只要将参数名写正确即可,这样可以避免用户需要牢记参数位置的麻烦,使得函数的调用和参数传递更加灵活方便。
例如,调用 fun_bmi(person,height,weight) 函数,通过关键字参数指定各个实际参数,代码如下:
fun_bmi( height = 1.83, weight = 60, person = "路人甲") #计算路人甲的 BMI 指数函数调用后,将显示以下结果:
路人甲的身高:1.83米体重:60千克
路人甲的 BMI 指数为:17.916330735465376
您的体重过轻从上面的结果中可以看出,虽然在指定实际参数时,顺序与定义函数时不一致,但是运行结果与预期是一致的。
为参数设置默认值
在调用函数时,如果没有指定某个参数将抛出异常,即在定义函数时,直接指定形式参数的默认值。这样,当没有传入参数时,则直接使用定义函数时设置的默认值。定义带有默认值参数的函数的语法格式如下:
def functionname(…,[parameter1 = defaultvalue1]):
[functionbody]参数说明如下:
- functionname:函数名称,在调用函数时使用。
- parameter1 = defaultvalue1:可选参数,用于指定向函数中传递的参数,并且为该参数设置默认值为 defaultvalue1 。
- functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。
注意:在定义函数时,指定默认的形式参数必须在所有参数的最后,否则将产生语法错误。
提示:在 Python 中,可以使用
"函数名._defaults_"查看函数的默认值参数的当前值,其结果是一个元组。例如,显示上面定义的fun_bmi()函数的默认值参数的当前值,可以使用”fun_bmi ._defaults_“,结果为”(‘路人’,)”。
另外,使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况。
说明:在定义函数时,为形式参数设置默认值要牢记一点:默认参数必须指向不可变对象。
可变参数
在 Python 中,还可以定义可变参数。可变参数也称为不定长参数,即传入函数中的实际参数可以是零个、一个、两个到任意个。
在定义可变参数时,主要有两种形式,一种是 *parameter ,另一种是 **parameter 。下面分别进行介绍。
1. *parameter
这种形式表示接收任意多个实际参数并将其放到一个元组中。
2. **parameter
这种形式表示接收任意多个类似关键字参数一样显式赋值的实际参数,并将其放到一个字典中。
返回值
到目前为止,我们创建的函数都只是为我们做一些事,做完了就结束。但实际上,有时还需要对事情的结果进行获取,这类似于主管向下级职员下达命令,职员去做,最后需要将结果报告给主管。为函数设置返回值的作用就是将函数的处理结果返回给调用它的程序。
在 Python 中,可以在函数体内使用 return 语句为函数指定返回值。该返回值可以是任意类型,并且无论 return 语句出现在函数的什么位置,只要得到执行,就会直接结束函数的执行。 return 语句的语法格式如下:
result = return [value]参数说明如下:
- result :用于保存返回结果,如果返回一个值,那么
result中保存的就是返回的一个值,该值可以是任意类型。如果返回多个值,那么result中保存的是一个元组。- value :可选参数,用于指定要返回的值,可以返回一个值,也可以返回多个值。
说明:当函数中没有
return语句时,或者省略了return语句的参数时,将返回 None ,即返回空值。
变量的作用域
变量的作用域是指程序代码能够访问该变量的区域,如果超出该区域,再访问时就会出现错误。在程序中,一般会根据变量的有效范围将变量分为全局变量和局部变量。
局部变量
局部变量是指在函数内部定义并使用的变量,它只在函数内部有效,即函数内部的名字只在函数运行时才会创建,在函数运行之前或者运行完毕之后,所有的名字就都不存在了。所以,如果在函数外部使用函数内部定义的变量,就会抛出 NameError 异常。
全局变量
与局部变量对应,全局变量为能够作用于函数内外的变量。全局变量主要有以下两种情况。
(1)如果一个变量在函数体外定义,那么不仅在函数外可以访问到,在函数内也可以访问到。在函数体以外定义的变量是全局变量。
说明:当局部变量与全局变量重名时,对函数体内的变量进行赋值后,不影响函数体外的变量。
(2)如果一个变量在函数体内定义,并且使用 global 关键字修饰后,该变量也就变为全局变量。在函数体外可以访问该变量,并且在函数体内还可以对其进行修改。
在函数内部定义的变量即使与全局变量重名,也不影响全局变量的值。那么想要在函数体内部改变全局变量的值,需要在定义局部变量时,使用 global 关键字修饰。
注意:尽管 Python 允许全局变量和局部变量重名,但是在实际开发时,不建议这么做,因为这样容易让代码混乱,很难分清哪些是全局变量,哪些是局部变量。
匿名函数(lambda)
匿名函数是指没有名字的函数,应用在需要一个函数,但是又不想费神去命名这个函数的场合。在通常情况下,这样的函数只使用一次。在 Python 中,使用 lambda 表达式创建匿名函数,其语法格式如下:
result = lambda [arg1 [,arg2,…,argn]]:expression参数说明如下:
- result:用于调用
lambda表达式。- [arg1[,arg2,…,argn ]]:可选参数,用于指定要传递的参数列表,多个参数间使用逗号 “,” 进行分隔。
- expression:必选参数,用于指定一个实现具体功能的表达式。如果有参数,那么在该表达式中将应用这些参数。
注意:使用
lambda表达式时,参数可以有多个,用逗号”,”进行分隔,但是表达式只能有一个,即只能返回一个值,而且也不能出现其他非表达式语句(如for或while)。
| dict([arg]) | 创建数据字典 |
| list([iterabl ]) | 将一个集合类转换为另外一个集合类 |
| set() | set 对象实例化 |
| frozenset([iterable]) | 产生一个不可变的 set |
| str([object]) | 转换为 string 类型 |
| sorted(iterable[cmp[,key[,reverse ]]]) | 队集合排序 |
| tuple([iterable]) | 生成一个 tuple 类型 |
| xrange([start ], stop[,step]) | xrange() 函数与 range() 函数类似,但 xrange() 函数并不创建列表,而是返回一个 xrange 对象,它的行为与列表相似,但是只在需要时才计算列表值,当列表很大时,这个特性能为我们节省内存 |
