Python程序设计基础与应用
上QQ阅读APP看书,第一时间看更新

5.2 函数参数

函数定义时圆括弧内是使用逗号分隔开的形参列表,函数可以有多个参数,也可以没有参数,但定义和调用函数时一对圆括弧必须要有,表示这是一个函数并且不接收参数。调用函数时向其传递实参,将实参的引用传递给形参。

5.2.1 位置参数

位置参数是比较常用的形式,调用函数时实参和形参的顺序必须严格一致,并且实参和形参的数量必须相同。

     > > > def demo(a, b, c):            #所有形参都是位置参数
        print(a, b, c)


> > > demo(3, 4, 5) 3 4 5 > > > demo(3, 5, 4) 3 5 4 > > > demo(1, 2, 3, 4) #实参与形参数量必须相同 TypeError: demo() takes 3 positional arguments but 4 were given

5.2.2 默认值参数

在定义函数时,Python支持默认值参数,即可以为形参设置默认值。在调用带有默认值参数的函数时,可以不用为设置了默认值的形参进行传值,此时函数将会直接使用函数定义时设置的默认值,当然也可以通过显式赋值来替换其默认值。

需要注意的是,在定义带有默认值参数的函数时,任何一个默认值参数右边都不能再出现没有默认值的普通位置参数,否则会提示语法错误。带有默认值参数的函数定义语法如下。

    def 函数名(…,形参名=默认值):
        函数体

例如,下面的函数定义:

     > > > def say( message, times =1 ):
    `   print((message+' ') * times)

调用该函数时,如果只为第一个参数传递实参,则第二个参数使用默认值“1”,如果为第二个参数传递实参,则不再使用默认值“1”,而是使用调用者显式传递的值。

     > > >  say('hello')
     hello
     > > >  say('hello', 3)
     hello hello hello

5.2.3 关键参数

关键参数主要指调用函数时的参数传递方式,通过关键参数可以按参数名字传递值,明确指定哪个值传递给哪个参数,实参顺序可以和形参顺序不一致,但不影响参数值的传递结果,避免了用户需要牢记参数位置和顺序的麻烦,使得函数的调用和参数传递更加灵活方便。

     > > > def demo(a, b, c=5):
        print(a, b, c)


> > > demo(3, 7) 3 7 5 > > > demo(a=7, b=3, c=6) 7 3 6 > > > demo(c=8, a=9, b=0) 9 0 8

5.2.4 可变长度参数

可变长度参数在定义函数时主要有两种形式:*parameter和**parameter,前者用来接收任意多个位置实参并将其放在一个元组中,后者接收多个关键参数并将其放入字典中。

下面的代码演示了第一种形式可变长度参数的用法,无论调用该函数时传递了多少实参,一律将其放入元组中。

     > > > def demo(*p):
        print(p)


> > > demo(1, 2, 3) (1, 2, 3) > > > demo(1, 2, 3, 4, 5, 6, 7) (1, 2, 3, 4, 5, 6, 7)

下面的代码演示了第二种形式可变长度参数的用法,在调用该函数时自动将接收的多个关键参数转换为字典中的元素。

     > > > def demo(**p):
        for item in p.items():
            print(item)


> > > demo(x=1, y=2, z=3) ('y', 2) ('x', 1) ('z', 3)

5.2.5 传递参数时的序列解包

与可变长度的参数相对应,这里的序列解包是指实参,同样也有*和**两种形式。调用含有多个位置参数的函数时,可以使用Python列表、元组、集合、字典以及其他可迭代对象作为实参,并在实参名称前加一个星号,Python解释器将自动进行解包,然后把序列中的值分别传递给多个形参变量。

     > > > def demo(a, b, c):                #可以接收多个位置参数的函数
        print(a+b+c)


> > > seq = [1, 2, 3] > > > demo(*seq) #对列表进行解包 6 > > > tup = (1, 2, 3) > > > demo(*tup) #对元组进行解包 6 > > > dic = {1:'a', 2:'b', 3:'c'} > > > demo(*dic) #对字典的键进行解包 6 > > > demo(*dic.values()) #对字典的值进行解包 abc > > > Set = {1, 2, 3} > > > demo(*Set) #对集合进行解包 6

如果实参是个字典,可以使用两个星号**对其进行解包,会把字典转换成类似于关键参数的形式进行参数传递。对于这种形式的序列解包,要求实参字典中的所有键都必须是函数的形参名称,或者与函数中两个星号的可变长度参数相对应。

     > > > p = {'a':1, 'b':2, 'c':3}         #要解包的字典
     > > > def f(a, b, c=5):                 #带有位置参数和默认值参数的函数
        print(a, b, c)


> > > f(**p) 1 2 3 > > > def f(a=3, b=4, c=5): #带有多个默认值参数的函数 print(a, b, c)

> > > f(**p) #对字典元素进行解包 1 2 3 > > > def demo(**p): #接收字典形式可变长度参数的函数 for item in p.items(): print(item)

> > > p = {'x':1, 'y':2, 'z':3} > > > demo(**p) #对字典元素进行解包,不要在意顺序 ('y', 2) ('z', 3) ('x', 1)