Python中的函数
函数可以解决大量代码重复、功能不清晰等问题,分为内置函数和自定义函数。
函数的作用:
- 通过函数,可以对功能进行详细的划分,在需要使用功能时,就可以调用该函数。
- 通过函数,可以避免代码的重复,实现代码的重用。
8.1 内置函数
print
input
abs
max
min
其他见过的类型转换函数等
8.2 函数的定义
函数是具有一定功能的代码块,该代码块可以重复的执行。
函数的定义方式如下:
def 函数名(参数列表):
函数体
8.2.1 关键字pass的使用
在程序设计时,我们可以先把程序划分成若干个功能,具体的实现可以后续再完成。可是,在Python中,函数不允许没有函数体,此时,我们就可以使用pass来进行占位。
pass表示空语句,用在函数中用来进行占位。不过,pass也可以放在选择与循环体中。
示例:
def func():
pass
8.2.2 函数的参数
如果把函数比喻成一台加工机器,参数就是被加工的原材料。在函数的定义中参数可以看作是一个占位符,它没有数据,只能等待函数被调用的时候接受传递进来的数据。
8.3 参数类型
8.3.1 位置参数
调用函数时根据函数定义的参数位置来传递参数。
示例:
def sum(a,b,c):
return a+b+c
sum(10,20,30)
output:
60
8.3.2. 默认值参数
如果形参含有默认值,则在函数定义时,含有默认值的形参一定要定义在不含默认值的形参之后。
这是因为,如果形参含有默认值,则意味着,该参数是一个可选参数,在函数调用时,可以选择性的进行传值。如果允许含有默认值的形参定义在不含默认值的形参前面,就会造成混淆。
示例:
def f( length=3,width, height=4):
print("length=",length)
print("width=",width)
print("heiht=",height)
f(5, 8)
output:
SyntaxError: non-default argument follows default argument
注意不要使用不可变对象作为默认值。
8.3.3 命名关键字参数
除了位置参数之外,还可以使用命名关键字参数。所谓命名关键字参数,就是在调用函数时,显式指定“参数名=参数值”的形式,即指定要给哪一个形参传递值。
同时,也可以在调用函数时,混合使用位置参数与关键字参数。但是位置参数放在前面。
关键字参数的作用很多,总结来说,关键字参数具有如下优势:
- 关键字参数能够增加程序的可读性。
- 关键字参数可以不用考虑传递的顺序。
- 当多个形参存在默认值时,关键字参数能够指定赋值给哪个形参。
增加程序的可读性
假设如下的函数:
def box_volume(length, width, height):
我们可以使用位置参数调用:
box_volume(10, 20, 30)
这样是没有问题的,不过,当参数较多的时候,可能会降低程序的可读性,因为我们需要确定每个参数具体代表的含义(此时可能就得重新查看一下函数的定义)。但是,使用关键字参数进行调用,就会变得清晰,增加了程序的可读性:
box_volume(length=10, width=20, height=30)
不用考虑传递顺序。
其次,如果使用位置参数,则必须严格要求按照顺序进行传递**,如果使用关键字参数,则无此限制,我们完全可以任意颠倒参数的顺序:
box_volume(width=20, length=10, height=30)
指定为哪一个形参赋值
再者,当函数存在多个默认值时:
def box_volume(length=3, width=4, height=5):
如果我们使用位置参数进行调用:
box_volume(10)
则实际参数10会赋值给length,然而,我们的原意未必总是想指定length,如果我们想指定width或height,而让另外两个参数取默认值,或者,想显式指定其中的两个,另外一个取默认值,该怎样实现呢?此时,我们就可以使用关键字参数来实现需求了。
box_volume(width=10)
在进行参数传递时,我们需要注意以下几点:
- 位置参数必须出现在关键字参数的前面。
- 同一个参数不能传递多次。(位置参数与关键字参数,或多个关键字参数)
- 关键字参数的顺序可以颠倒,但是提供的参数名必须存在。
强制使用关键字参数
之前说过,使用关键字参数可以显式指定实参要赋值给哪一个形参,这样就可以提高程序的可读性。通常情况下,对于可选的参数(含有默认值的参数),因为其存在的不确定性,因此,如果需要为可选参数传值,在调用时往往使用关键字参数是一种好的选择。不过,到底使用位置参数,还是关键字参数,完全取决于函数的调用者,函数的定义者并没有能力进行控制。也就是说,程序员A在调用函数时,可能会使用关键字参数,而程序员B却使用位置参数。为了能够增强程序的可读性,同时实现编程风格的一致性,函数的定义者可以使用“”语法,来限制“”后面的所有参数必须都是以关键字参数的形式传递。
说明:
- 强制使用关键字往往针对的是具有默认值的参数,但从语法的角度讲,对于不含默认值的参数,也是可以的。
8.3.4 可变参数
定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。可变参数(*),也可以叫收集参数。
函数调用时,位置可变参数(形参)可以用来接收所有未匹配的位置参数(实参)并封装成元组传递给函数。
def func(*args):
print(type(args))
print(*args)
func(10,20,"str")
output:
<class 'tuple'>
10 20 str
我们传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
8.3.5 关键字参数
关键字可变参数(形参)可以用来接收所有未匹配的关键字参数(实参)。所有未匹配的关键字参数会打包成一个字典。
对于关键字可变参数,可以用来接收一些可选的选项,设置等。对于选项较多时,如果将每个选项都用一个关键字参数来接收时,会显得函数定义特别庞大,此时,就可以使用一个关键字可变参数来实现。
例如,在Requests库中,get函数定义为:
requests.get(url, params=None, **kwargs)
其中,kwargs是一个字典,可以接收很多选项,例如data,headers,cookies,files等。
示例:
def func(a,b,**kwargs):
print(type(kwargs))
print(kwargs)
for i in kwargs.items():
print (i)
func(10,20,c=5,d=10)
output:
<class 'dict'>
{'c': 5, 'd': 10}
('c', 5)
('d', 10)
对于可变参数,我们需要注意如下事项:
- 可变参数只能接收未匹配的(剩下的)实际参数,如果实际参数已经匹配某形式参数,则不会由可变参数接收。
- 在参数位置上,关键字可变参数必须位于函数参数列表的最后。
- 在位置可变参数后面定义的参数,将自动成为关键字参数。(为什么)
- 位置可变参数与关键字可变参数各自最多只能定义一个。
8.3.6 参数组合
几种参数可以组合使用,可变参数和命名关键字参数不可混合(两个单独带*的)。
其余参数的顺序必须是:
必选参数,默认参数,命名关键字参数/ *args, **kwargs