我们已经学过Python函数的无参数形式和按位传值参数形式,这一课里全面说明Python函数的参数形式。
一、带默认值的参数
分数由分子和分母构成,但为什么不输入参数和只输入分子
>>>from fractions import Fraction
>>>Fraction(123)
Fraction(123, 1)
>>>Fraction()
Fraction(0, 1)
也能构造成分数呢?原来输入的参数有默认值
class fractions.Fraction(numerator=0, denominator=1)。
分子(numerator)的默认是0,分母(denominator)的默认值是1,当只输入分子123时,分母采用默认值1,所以构成的分数是Fraction(123, 1);都不输入时,分子默认0,分母默认1,所以构成的分数是Fraction(0, 1)。
默认值是在函数定义处被计算的,并且只会执行一次,所以
i = 5 #i被赋值5
def f(arg=i): #arg的默认值被赋值i,因为这时i=5,所以arg的默认值是5
print(arg)
i = 6 #i被赋值6,但arg的默认值不会被重新计算。
f()
会打印 5;
def f(a, L=[]): #L的默认值是一个列表(已固定,可编辑元素)
L.append(a) #往列表中添加元素
return L #返回列表
print(f(1)) #采用默认值调用函数
print(f(2))
print(f(3))
print(f(4, [])) #不采用默认值调用函数
这将打印出
[1]
[1, 2]
[1, 2, 3]
[4]
。如果你不想要在后续调用之间共享默认值,采用None默认值,并且在函数体内对输入对象初始化,你可以这样写这个函数:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
print(f(1)) #采用默认值调用函数
print(f(2))
print(f(3))
print(f(4, [])) #不采用默认值调用函数
将打印出
[1]
[2]
[3]
[4]
。
有默认值的参数务必要在无默认值的参数后:
。
二、关键字调用函数
下面是输入初一(7)班学生的姓名,性别和年龄的程序
因为黄小丽的年龄是默认值12岁,就不输入年龄,但结果打印出
。为什么电脑不按你的意思工作呢?因为你采用的是按位调用函数,“黄小丽”赋值给name,“女”赋值给age,sex不输入就采用默认值“男”。如果使用按位调用,只能这样调用
。age的默认值没用上。
有没有方法不用输入age,也不会出错的呢?
有!就是关键字调用函数。原来函数的参数名称,对于函数体内是形式参数名称,对于调用者不但是入口参数名称,也是入口参数的“关键字”。只要使用
关键字=值
的形式调用函数,就可以精准赋值。修改后的程序和结果如下:
。从上图中可以看到,按位传值和关键字传值可以同时使用,这样就要注意不能重复传值
。
三、任意的参数列表
如果还要输入学生的家长(可以多个,数量不定),就要加入一个任意的参数列表(在标识符前加一个*),修改程序
打出的结果
,显然,结果是错的!原来任意的参数列表(*pOrg)之前不可以有有默认值的参数(在Python中认为有默认值的参数是键值参数),进一步修改程序
打出的结果
,OK了!也注意到,任意的参数列表是一个元组。
四、任意的参数字典
比如还要输入爱好、最喜欢的食物、专长、最喜欢的歌等等一些项目,就要采用"任意的参数字典",在参数之前加**。再修改程序
,语法错误!原来任意的参数字典只能放在参数最后。再修改程序
打出的结果
OK了。也注意到任意的参数字典是一个字典数据类型。
五、特殊参数
如果学生的名字总是第一个参数,希望仅按位传值;性别和年龄两个参数如果按位传值容易搞错,规定仅按关键字传值;把家长这个任意的参数列表变更为父亲、母亲、其他亲属(任意的参数列表)0到多个家长,可以按位也可以按关键字传值,应该怎样做呢?
限位置传值的参数一定要放在前面,在这些参数之后放一个特殊参数"/"(正斜杠);限关键字传值的参数一定要放后面,在这些参数之前放一个特殊参数"*"(星号);在"/"和"*"之间的参数可以按位也可以按关键字传值。程序修改如下
,有语法错误!原来在参数“*other_rels”之后的参数“*”是多余的了,因为参数“*other_rels”之后的参数一定要通过键值才能输入,把程序修改为
后,打印出的结果
OK了。
六、解包参数列表
与参数的打包(任意的参数列表和任意的参数字典)相对,要把列表、元组或字典解包成单独的参数,就是解包参数。举例说明:
解包列表或元组,在调用函数时,在列表或元组之前加“*”号,打出的结果
显然,数据解包后正确传给了相应的参数;
解包字典,在调用函数时,在字典之前加“**”号,打出的结果
显然,数据解包后正确传给了相应的参数。
练习题:按本课的测试,输入代码自行测试一次。