zoukankan      html  css  js  c++  java
  • 18.函数的参数

    1.实参与形参介绍

    • 形参:函数定义阶段时括号内声明的参数
    • 实参:函数调用时,括号内传入的值,值可以是常量、变量、表达式或三者的组合

    总结:在python中,变量名与值只是单纯的绑定关系,而对于函数来说,绑定关系只是在调用时生效,在调用后解除

    2.形参与实参的具体使用

    • 位置参数(形参、实参)

      • 位置形参:在定义函数时,按照从左到右的顺序依次定义形参,称为位置形参,必须被传值
      def register(name,age,sex): #定义位置形参:name,age,sex,三者都必须被传值
          print('Name:%s Age:%s Sex:%s' %(name,age,sex))
      register() #TypeError:缺少3个位置参数 
      
      • 位置实参:在调用函数时,按照从左到右的顺序依次定义参数,称为位置实参,会按照从左到右的顺序与形参一一对应
    • 关键字参数(实参)

      在调用函数时,实参是可以key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值

      >>> register(sex='male',name='lili',age=18)
      Name:lili Age:18 Sex:male
      

      需要注意在调用函数时,实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值

      >>> register('lili',sex='male',age=18) #正确使用
      >>> register(name='lili',18,sex='male') #SyntaxError:关键字参数name=‘lili’在位置参数18之前
      >>> register('lili',sex='male',age=18,name='jack') #TypeError:形参name被重复赋值
      
    • 默认参数(形参)

      在定义函数时,就已经为形参赋值,称为默认参数。当函数需要多个参数时,需要将经常更改的参数定义成位置参数,而将值改变较少的参数定义成默认参数。例如白写一个注册学生信息的函数,如果大都为男,则可以将性别sex定义成默认参数,默认参数的值一般是不可变类型

      >>> def register(name,age,sex='male'): #默认sex的值为male
      ...     print('Name:%s Age:%s Sex:%s' %(name,age,sex))
      ...
      

      若要默认参数可变,可如下所示

      def foo(n,arg=None):    
           if arg is None:    
               arg=[]    
           arg.append(n)    
           return arg 
      

      定义时就已经为参数sex赋值,意味着调用时可以不用对sex赋值,这降低了函数调用的复杂度

      >>> register('tom',17) #大多数情况,无需为sex传值,默认为male
      Name:tom Age:17 Sex:male
      >>> register('Lili',18,'female') #少数情况,可以为sex传值female
      Name:Lili Age:18 Sex:female
      

      注意:默认参数必须在位置参数之后

      ​ 默认参数的值仅在函数定义阶段被赋值一次,指向的是内存地址

      >>> x=1
      >>> def foo(arg=x):
      ...     print(arg)
      ... 
      >>> x=5 #定义阶段arg已被赋值为1,此处的修改与默认参数arg无任何关系
      >>> foo()
      1
      

    3.可变长度参数(*args与**kwargs)

    • *args

    在形参中使用*args,溢出的位置实参,都会以元组的形式保存下来赋值给改形参

    >>> def foo(x,y,z=1,*args): #在最后一个形参名args前加*号
    ...     print(x)
    ...     print(y)
    ...     print(z)
    ...     print(args)
    ... 
    >>> foo(1,2,3,4,5,6,7)  #实参1、2、3按位置为形参x、y、z赋值,多余的位置实参4、5、6、7都被*接收,以元组的形式保存下来,赋值给args,即args=(4, 5, 6,7)
    
    1
    2
    3
    (4, 5, 6, 7)
    

    *在实参中的使用

    >>> def foo(x,y,*args):
    ...     print(x)
    ...     print(y)
    ...     print(args)
    ... 
    >>> L=[3,4,5]
    >>> foo(1,2,*L) # *L就相当于位置参数3,4,5, foo(1,2,*L)就等同于foo(1,2,3,4,5)
    1
    2
    (3, 4, 5)
    

    如果实参中没有*,则相当于一个普通位置参数(列表)

    >>> foo(1,2,L) #仅多出一个位置实参L
    1
    2
    ([1, 2, 3],)
    

    如果形参为常规的参数(位置或默认),实参仍可以是*的形式

    >>> def foo(x,y,z=3):
    ...     print(x)
    ...     print(y)
    ...     print(z)
    ... 
    >>> foo(*[1,2]) #等同于foo(1,2)
    1
    2
    3
    

    例如用*args求和

    def add(*args):
        res = 0
        for i in args:
            res +=i
        return res
    
    res = add(1,2,3,4,5)
    print(res)
    
    
    • **kwargs

    如果在最后一个形参名前加加好,那么在调用函数时,溢出的关键字参数,都会被接收,以字典的形式赋值给该形参

    >>> def foo(x,**kwargs): #在最后一个参数kwargs前加**
    ...     print(x)        
    ...     print(kwargs)   
    ... 
    >>> foo(y=2,x=1,z=3) #溢出的关键字实参y=2,z=3都被**接收,以字典的形式保存下来,赋值给kwargs
    1
    {'z': 3, 'y': 2}
    

    若事先声明一个字典,也是可以传值给**kwargs

    >>> def foo(x,y,**kwargs):
    ...     print(x)
    ...     print(y)
    ...     print(kwargs)
    ... 
    >>> dic={'a':1,'b':2} 
    >>> foo(1,2,**dic) #**dic就相当于关键字参数a=1,b=2,foo(1,2,**dic)等同foo(1,2,a=1,b=2)
    1
    2
    {'a': 1, 'b': 2}
    

    若没有加**,则是一个普通的字典,dic就是一个位置参数,会报错(需要两个,传入三个)

    >>> foo(1,2,dic) #TypeError:函数foo只需要2个位置参数,但是传了3个
    

    如果形参为常规参数(位置或默认),实参仍可以是**的形式

    >>> def foo(x,y,z=3):
    ...     print(x)
    ...     print(y)
    ...     print(z)
    ... 
    >>> foo(**{'x':1,'y':2}) #等同于foo(y=2,x=1)
    1
    2
    3
    

    4.命名关键字参数

    在定义了**kwargs参数后,函数调用者就可以传入任意的关键字参数key=value,如果函数体代码的执行需要依赖某个key,必须在函数内进行判断

    >>> def register(name,age,**kwargs):
    ...     if 'sex' in kwargs:
    ...         #有sex参数
    ...         pass
    ...     if 'height' in kwargs:
    ...         #有height参数
    ...         pass
    ...
    

    想要限定函数的调用者必须以key=value的形式传值,Python3提供了专门的语法:需要在定义形参时,用作为一个分隔符号,号之后的形参称为命名关键字参数。对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值

    >>> def register(name,age,*,sex,height): #sex,height为命名关键字参数
    ...     pass
    ... 
    >>> register('lili',18,sex='male',height='1.8m') #正确使用
    >>> register('lili',18,'male','1.8m') # TypeError:未使用关键字的形式为sex和height传值
    >>> register('lili',18,height='1.8m') # TypeError没有为命名关键字参数sex传值。
    

    命名关键字参数也可以有默认值,从而简化调用

    >>> def register(name,age,*,sex='male',height):
    ...     print('Name:%s,Age:%s,Sex:%s,Height:%s' %(name,age,sex,height))
    ... 
    >>> register('lili',18,height='1.8m')
    Name:lili,Age:18,Sex:male,Height:1.8m
    

    需要强调的是:sex不是默认参数,height也不是位置参数,因为二者均在后,所以都是命名关键字参数,形参sex=’male’属于命名关键字参数的默认值,因而即便是放到形参height之前也不会有问题。另外,如果形参中已经有一个args了,命名关键字参数就不再需要一个单独的*作为分隔符号了

    >>> def register(name,age,*args,sex='male',height):
    ...   print('Name:%s,Age:%s,Args:%s,Sex:%s,Height:%s' %(name,age,args,sex,height))
    ... 
    >>> register('lili',18,1,2,3,height='1.8m') #sex与height仍为命名关键字参数
    Name:lili,Age:18,Args:(1, 2, 3),Sex:male,Height:1.8m
    

    5.组合顺序

    所有参数可以任意组合使用,顺序为:位置参数,默认参数,*args,命名关键字参数,**kwargs

    • 可变参数*args与关键字参数kwargs通常是组合在一起使用的,如果一个函数的形参为*args与kwargs,那么代表该函数可以接收任何形式、任意长度的参数
    >>> def wrapper(*args,**kwargs):
    ...     pass
    ...
    
    • 函数内部传值
    >>> def func(x,y,z):
    ...     print(x,y,z)
    ... 
    >>> def wrapper(*args,**kwargs):
    ...     func(*args,**kwargs)
    ...
    >>> wrapper(1,z=3,y=2)
    1 2 3
    
    1. 位置实参1被*接收,以元组的形式保存下来,赋值给args,即args=(1,),关键字实参z=3,y=2被**接收,以字典的形式保存下来,赋值给kwargs,即kwargs={'y': 2, 'z': 3}
    2. 执行func(args,kwargs),即func(*(1,),** {'y': 2, 'z': 3}),等同于func(1,z=3,y=2)
  • 相关阅读:
    树形地铁系统[树的最小表示]
    156. 矩阵[二维的hash]
    兔子与兔子
    滑动窗口【单调队列入门题】
    【YBTOJ】生日相同
    【YBTOJ】移位包含
    【YBTOJ】【HDUOJ 3085】逃离噩梦
    【YBTOJ】立体推箱子
    【CodeForces 1408F】Two Different
    【Luogu P3338】[ZJOI2014]力
  • 原文地址:https://www.cnblogs.com/Psc-mmf/p/13933180.html
Copyright © 2011-2022 走看看