python之函数的参数

函数的参数

一、形参与实参介绍

  1. 引入

    • 函数的参数分为2大类,一个是函数定义阶段,另一个是函数调用阶段。

  2. 什么是形参?

    • 定义阶段的参数

    • 在定义函数阶段,定义的形式参数,称之为形参。形参本质就相当与变量名

  3. 什么是实参?

    • 调用阶段的参数。

    • 在调用函数阶段传入的值称之为实际参数,简称实参。实参本质相当于变量值。

      • 实参即在调用函数时,括号内传入的值,值可以是常量、变量、表达式或三者的组合:

  4. 什么时候形参会申请内存空间?

    函数调用阶段,传参的时候,实参(值)会赋值给形参(变量名),形参就会申请内存空间。这和变量的定义一样,我们所知只有一个变量名,并没有申请内存空间,当有变量值与之绑定的时候,这个时候就会发生申请内存空间把值存入。

  5. 调用函数时二者的关系

    1. 绑定关系:在调用阶段,实参的值(变量值)会绑定给形参(变量名)

    2. 使用范围:且含有这种绑定关系的参数只能在函数体内使用

    3. 生效时间:实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系

# 实参是传入的值,但值可以是以下形式(小结:可以这么理解只要实参传入的结果最终结果是一个值就可以)
# 形式一:
def func(x,y):
    print(x,y)
func(1,2)
​
# 形式二:
def func(x,y):
    print(x,y)
a=1
b=2
func(a,b)
# 形式三:
func(int('1'), 2)
func(func1(1, 2), func2(2, 3), 333)

二、形参与实参具体使用

位置参数:位置形参、位置实参

按照从左到右的顺序依次定义的参数称之为位置参数

位置参数分为两种:

  1. 位置形参:

    • 大前提:函数定义阶段,按照从左到右的顺序直接定义的“变量名”。

    • 特点:必须被传值,多个一个不行,少一个也不行。

  def func(x, y):
      print(x, y)
      
  # 多一个不行
  # func(1, 2, 3)  # 报错:类型错误(TypeError: func() takes 2 positional arguments but 3 were given)
  
  # 少一个不行
  # func(1, )  # 报错:类型错误(TypeError: func() missing 1 required positional argument: 'y')
  1. 位置实参:

    • 大前提::函数调用阶段。按照从左到右的顺序依次传入值。

    • 特点:按照顺序与形参一一对应传值。(真正按照顺序是在传参的时候,且实参必须遵形参的规则)

      实例一:
      func(1, 2)  # 1给了x, 2给了y。返回结果:1 2
      func(2, 1)  # 2给了x, 1给了y。返回结果:2 1
      ​
      实例二:
      def register(name ,age ,sex):
          print("name:%s age:%s sex: %s" %(name ,age,sex))
      register("egon",19,"male")

       

关键字参数:关键字实参

关键字实参

大前提:大前提:在函数调用阶段。按照key=value的形式传值。

特点:指名道姓的给某个形参传值,可以完全不参照顺序。(实参必须遵形参的规则)

def func(x, y):
    print(x, y)
​
func(y=2, x=1)
func(x=1, y=2)

位置实参与关键字实参传值混合使用:

# 1、位置实参必须放在关键字实参之前
def func(x,y):
    print(x,y)
func(1, y=2)    # 1给了x, 2给了y。返回结果:1 2
func(y=2, 1)  # 报错,语法错误:SyntaxxError
​
# 2、不能给同一个形参重复传值
def func(x,y):
    print(x,y)
func(1,y=2,x=3) # 1给了x, 2给了y,3又给了x重复传值。报错(TypeError)

默认参数:指的是默认形参

默认形参(具有默认值的形参)

大前提:定义函数阶段。就已经被赋值的形参。

特点:在定义阶段就已经被赋值,意味着在调用的阶段可以不为其传值(不传也行,传也行)

介绍

def func(x, y=3):
    print(x, y)
func(x=1)  # 1 3
func(x=1, y=444)  # y有默认值,但是你就就想传,就以你传的为准。 返回结果:1 444
​

应用场景

用在经常不变,大多数情况都是一样得情况。比如用户注册,用户没有设置密码,那么我们给一个默认密码。这个时侯就用到了默认参数。

def register(name, age, password='123'):
    print(name, age, password)
​
register('吴三炮', 18)  # 三炮 18 123
register('四炮', 18)  # 四炮 18 123
register('五炮', 18)  # 五炮 18 123
register('六炮', 18, password='111')  # 六炮 18 111 

需要注意:

  1. 默认参数必须在位置参数之后

  2. 默认参数的值仅在函数定义阶段赋值一次

    x=1
    def foo(arg=x):
        print(arg)
    x=5  #定义阶段arg已被赋值为1,此处的修改与默认参数arg无任何关系
    foo() #返回值 1
    
  3. 默认参数的值通常应设为不可变类型

    def foo(n,arg=[]):    
         arg.append(n)    
         return arg    
    foo(1)    
    [1] 
    foo(2)    
    [1, 2] 
    foo(3)    
    [1, 2, 3]
    
    • 每次调用是在上一次的基础上向同一列表增加值,修改如下

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

综合应用:

位置实参与关键字实参:

注意:位置实参与关键字实参可以用混用,但是必须注意

  1. 位置实参必须放在关键字实参的前面

  2. 不能为同一个形参重复赋值

    def func(x,y=2222):
        print(x,y)
    func(1,y=2)
    func(y=2,1)  #位置实参必须在关键字实参的前面
    func(1,y=2,x=3) #不能为同一个参重复赋值
    

位置形参与默认形参:

注意:位置形参与默认形参可以混用,但是必须注意

  1. 顺序问题:位置形参必须在默认形参左边

    # def func(y=2, x):  #  位置形参必须在默认形参前,否则报错,语法错误(SyntaxError)
    #     pass
    
  2. 默认参数的值是在什么阶段被赋予的?赋予时间:默认参数的值是在函数定义阶段就被赋予的。 赋予结果:被赋予的是值得内存地址

    • 强调内容:

      • 内存地址是什么?

        • 内存地址是对值得一种引用。

      • 内存地址的传递 == 引用传递:

        • 有的人说python所有的传递,参数的传递也好、变量的传递也好,所有的传递都是内存地址的传递,在python中所有得传递传的起始不是值,都是内存地址的传递。

        • 又有的人说内存地址就是基于值得引用,所以有的人会说,python的传递都是“引用传递”。他说指的应用传递,其实都是内存地址的传递。

    • 实例一:

      • 默认形参的值是在函数定义阶段就规定死了,之后的改变不影响

      m = 2
      def func(x, y=m):  # y=m这里把m得内存地址给了y,也就是把值2得内存地址给了y。
          print(x, y)  # 1 2
      m = 3333333333  # 定义func阶段已经过去了,m自己在那里玩
      func(1)
      
    • 实例二:

      • 默认形参的值若为可变类型,则会被函数定义后的改变所影响

      m = [111, ]
      def func(x, y=m):  # y=m这里y拿到的是m对应的内存地址,而我们在外面定义的m是一个容器类型列表,所以y拿到的就是一个容器的内存地址,这个内存地址与上面定义的m绑定内存地址都是一致的,同一个内存地址。当我们下面用m.append操作时,把值追加到了m中,所以y中所关联的的值也会改变。
          print(x, y)  # 1 [111,333]
      m.append(333)
      func(1) # 1 [111, 333]
      print(m)  # [111, 333]
      ​
      
  3. 默认值使用类型:默认值可以被指为任意数据类型,但是并不推荐使用可变类型(补充:定义函数默认值形参最理想的结果就是预知它能拿到的结果,也可以说默认值的输出必须是靠谱的(不可变类型)。)

    • 默认形参的值若为可变类型,则会被函数定义后的改变所影响

      n=[10, 20]
      print(f"函数定义前 n: {id(n)}" )
      def f1(x,y=n): #在定义阶段,y指向的内存地址已经固定
          print(f"函数内 y: {id (y)}" )
          print(x,y)
      n.append(30)    #n 的值为可变类型,在值该改变内存地址不变,还是指向同一个内存地址
      print(f"函数定义后 n: {id(n)}")
      f1(222)
      ​
      函数定义前 n: 1402298802688
      函数定义后 n: 1402298802688
      函数内 y: 1402298802688
      222 [10, 20, 30]
      ​
      示例二:
      def register(name,hobby,hobbies=[]):
          hobbies.append(hobby)
          print('%s 的爱好是%s'%(name,hobbies))
      register("egon", "smoke")
      register("lxx","lang")
      register("hxx","drink")
      # 因为hobbies是个列表,为可变类型,输出结果如下
      egon 的爱好是['smoke']
      lxx 的爱好是['smoke', 'lang'] #lxx的爱好里有egon的爱好
      hxx 的爱好是['smoke', 'lang', 'drink'] #导致hxx的爱好里有lxx、egon的爱好
      

      需求:传入的值生成一个列表,且每次调用的结果都要拿到上一次操作结果继续。

      def func(x, y, z, li=[]):
          li.append(x)
          li.append(y)
          li.append(z)
          print(li)
      func(1, 2, 3)  # [1, 2, 3]
      func(4, 5, [6, 7])  # [1, 2, 3, 4, 5, [6, 7]]
      
    • 默认形参的值是在函数阶段定义规定死,之后的改变不会影响,默认形参的值最好为不可变类型。

      n=20
      print(f'函数定义前 n: {id(n)}') 
      def f1(x,y=n): #在定义阶段,所指向的内存地址已经被固定死
          print(f'函数内y: {id(y)}')
          print(x,y)
      n=111 #n的值为不可变类型,在值改变后内存地址也改变,但不会影响函数已定义的值
      print(f'函数定义后 n: {id(n)}')
      f1(222) 
      ​
      函数定义前 n: 140714925492480
      函数定义后 n: 140714925495392
      函数内y: 140714925492480
      222 20
      ​
      以上示例二优化如下:
      def register(name,hobby,hobbies=None):
          if hobbies is None:
              hobbies=[]
          hobbies.append(hobby)
          print('%s 的爱好是%s'%(name,hobbies))
      register("egon", "smoke")
      register("lxx","lang")
      register("hxx","drink")
      ​
      输出结果如下:
      egon 的爱好是['smoke']
      lxx 的爱好是['lang']
      hxx 的爱好是['drink']
      

      需求:传入的值生成一个列表,且每次调用的结果都是必须保证独立的列表。如果用户传入列表,那么就按照用户的为准。

    def func(x, y, z, li=None):
        if li is None:
            li = []
        li.append(x)
        li.append(y)
        li.append(z)
        print(li)
    func(1, 2, 3)  # [1, 2, 3]
    func(4, 5, [6, 7])  # [4, 5, [6, 7]]
    

可变长度的参数(***的用法)

一、可变成长度的位置参数:值得是可变长度的位置形参

引入可变长度的意义所在:

可变长度指的是在调用函数时,传入的值(也就是实参)的个数不固定。

注意:实参是用来为形参赋值的,所以针对溢出的实参必须要有对应的形参来接收。(必须要有对应的可以接收位置的形参)

*号的使用方法:

  • *形参名:用来接收溢出的位置实参。溢出的位置实参会被*号保存成元组的形式,赋值给紧跟其后的形参名。

*号功能介绍:

*后跟的可以是任意名字,但是为了规范性*后面跟的得变量名要使用args(提示:以后看到*后面的args,就直接看成元组)

形参中的应用:

在形参中带**会将溢出位置实参汇总成元组,然后赋值给其后变量名,通常应该是args

基本使用介绍:

def func(x, y, *z):
    print(x, y, z)
func(1, 2, 3, 4, 5, 6)  # 3456是多出来的实参,返回结果:1 2 (3, 4, 5, 6)

应用场景:写一个求和功能,无论用户传几个数,都把这些数字加起来。

# 不规范
def my_sum(*num_tuple):
    res=0
    for num in num_tuple:
        res += num
    return res
res=my_sum(1,2,3)
print(res)
​
# 规范 args就是一种变量名,一种规范
def my_sum(*args):
    res = 0
    for num in args:
        res += num
    return res
​
res = my_sum(1, 2, 3, 4 , 5, 6, 7, 8, 9)  
print(res)  # 45

实参中的应用:

*号用在实参中:*会把紧跟其后的实参打散成位置实参(本质原理可以理解为for循环取值)

def func(a,b,c,d,e):
    print(a,b,c,d,e)
func(*"hello") # h e l l o
func(*[1, 2, 3])  # 11 22 33 44 55
func(22,33,*[1,2,3]) # 22 33 1 2 3

拓展:*可以打散字典,但是只是把字典的key打散,当作位置实参传值。

def func(a,b,c,d,e):
    print(a,b,c,d,e)
func(11,22,33,*{"k1":33,"k2":444}) #11 22 33 k1 k2

综合应用:

形参与实参中都带*:(提示:只要是可以被for循环的,都可以是用*打散)

def func(x, y, *args):
    print(x, y , args)
func(1, 2, [3, 4, 5])   # 1, 2, [(3, 4, 5),]。分析:把1给了x,把2给了y。把[3, 4, 5]给了*号,*号在把[3, 4, 5]按照顺序存入元组中,交个args。args就是:([3, 4, 5], )
​
func(1, 2, *[3, 4, 5])  # 1, 2, (3, 4, 5)。分析:把1给了x,把2给了y,*号把[3, 4, 5]打散成按照顺序放置的位置实参,把3,4,5给了*号,*号将其按照顺序存入元组中。args就是:(3,4,5)
​
func(*'hello')  # h e ('l', 'l', 'o') 分析:*号把'hello'打散成按照顺序放置的位置实参 h,e,l,l,o, 接着把‘h’给了x,把‘e’给了y。剩下的‘l,l,o’给了*号。*号将其按照顺序存入元组中。args就是:(l,l,o)

二、可变长度的关键字参数:值得是可变长度的关键字形参

**使用方法:

**形参名:用来接收溢出的关键字实参。**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的变量(形参)名。通常应该是kwargs

**功能介绍:

**后跟的可以跟任意名字,但是为了规范性**后面跟的得变量名要使用kwargs(提示:以后看到**后面的后面跟的得变量名要使用kwargs,就直接看成字典)

形参中的应用:

**用在形参中:可以接收关键字实参溢出得值,保证关键字传值得可扩展性

def func(x, y, **kwargs):
    print(x, y, kwargs)
func(1, y=2, a=3, b=4, c=5)  # 注意:y=2并不是溢出的。abc才是,返回结果:1 2 {'a': 3, 'b': 4, 'c': 5}

实参中的应用:

在实参带 **:**会将紧跟其后的实参打散成关键字实参,注意:**后跟的必须是一个字典

def func(x, y, z):
    print(x, y, z)
func(*{'x': 1, 'y': 2, 'z': 3})  # 注意:一个*号可以打散字典,但是打散以后打散的是字典的key,因为我们之前说过*号类似于for循环,而for循环默认循环的就是字典的key,所以实际传参可以看成fuc('x', 'y', 'z')。打印结果:x y z
​
func(**{'x': 1, 'y': 2, 'z': 3})  # **将字典打散,打散以后的结果func('x'=1, 'y'=2, 'z'=3)。打印结果:1 2 3
    
# 错误:对定义的位置形参传值,多一个不行少一个不行
# func(**{'x': 1, 'y': 2})  # 打散以后func(x=1, y=2),传值不对等
​
# 错误:打散后形成的关键字参数不匹配
func(**{'x': 1, 'a': 2, 'y': 3})  # 打散以后func(x=1, a=2, y=3),没有a这个形参可以指定。

综合应用:

实参中与形参中都带**

def func(x, y, **kwargs):
    print(x, y, kwargs)
func(y=222, x=111, a=333, b=444)  # a、b作为溢出的关键字参数,传给**,由**接收以后转化成字典格式{'a': 333, 'b': 444}交给kwargs.返回结果:111 222 {'a': 333, 'b': 444}
func(**{'y': 222, 'x': 111, 'a': 333, 'b': 444})  # 由**打散变成func(y=222, x=111, a=333, b=444),再传给**,由**接收以后转化成字典格式{'a': 333, 'b': 444}交给kwargs.返回结果:111 222 {'a': 333, 'b': 444}

三、***混用:

  1. 在形参中,*args必须在** kwargs之前

  2. 在实参中,*args必须在** kwargs之前

    示例一:

    def weapper(*args, **kwargs):
        print(args,kwargs)
    weapper(1,2,3,4,a=1,b=2,c=3) #(1, 2, 3, 4) {'a': 1, 'b': 2, 'c': 3}
    

    实例二:

    def index(x,y,m,n,a,b,c):
        print("index========>",x,y,m,n,a,b,c)
    def wrapper(*args,**kwargs): # args=(1,2,3,4)  kwargs={"a":1,"b":2,"c":3}
        index(*args,**kwargs) # index(*(1,2,3,4),**{"a":1,"b":2,"c":3})
                            # index的值为(1,2,3,4,a=1,b=2,c=3)
    wrapper(1,2,3,4,a=1,b=2,c=3) #index========> 1 2 3 4 1 2 3
    ​
    #传给wrapper的值会调用index函数并赋值给index
    

    实例三:

    def index(x,y,z):
        print("index========>",x,y,z) 
    def wrapper(*args,**kwargs):
        index(*args,**kwargs)
    wrapper(1,2,3,4,a=1,b=2,c=3)    #直接报错语法错误,因为虽然看起来是给 wrapper赋值传参数,但正真用的是index
    wrapper(1,2,3) #index========> 1 2 3
    

    示例四:

    def index(x,y,z):
        print("index========>",x,y,z)
    def wrapper(*args,**kwargs):
        index(*args,**kwargs)
    wrapper(z=3,y=2,x=1) #index========> 1 2 3
    

作用:

  1. 主要用来增加拓展性

  2. 形参精简,不冗余

    def func(x, *args, **kwargs): 
        print(x)  # 1
        print(args)   # (2, 3, 4)       
        print(kwargs)    # {'y': 6, 'z': 7} 
    func(1, 2, 3, 4, y=6, z=7)  # 位置实参1,把值15的内存地址传递给x,然后位置实参溢出的交给args:(2, 3, 4)。关键字实参没有匹配的,接着把关键字实参溢出的交给kwargs: {'y': 6, 'z': 7}  
    

四、装饰器铺垫:了解在调用外层函数给内层函数传值的意义

  1. 刨析出在调用外层函数给内层函数传值的限制及扩展性差的问题

    def index(x, y, z):       
        print('index====>', x, y, z)
    def wrapper(a, b, c):  # wrapper的参数受制于index
        index(a, b, c)  # index应该怎么变,也就是说wrapper参数就得怎么变
    wrapper(1, 2, 3)  # 这里为wrapper传的参数,是给index用的
    
  2. 需求:我想调用的函数的格式,原封不动的当作实参转嫁给里面的函数,我们就用下面的这种格式:(提示:wrapper中传参取决于index中的形式参数的限)

    def index(x, y, z):       
        print('index====>', x, y, z)
    def wrapper(a, b, c):  # wrapper的参数受制于index
        index(a, b, c)  # index应该怎么变,也就是说wrapper参数就得怎么变
    wrapper(1, 2, 3)  # 这里为wrapper传的参数,是给index用的  
    
  3. 魔鬼练习

    def index(x, y, z):
        print('=====>', x, y, z)
    ​
    ​
    def wrapper(*args, **kwargs):
        index(*args, **kwargs)
    ​
    ​
    # 打印1,2,3
    wrapper(1, 2, 3)  # 第一步:wrapper(*(1, 2, 3), **{}) 第二步:index(1, 2, 3)
    wrapper(1, 2, z=3)  # 第一步:wrapper(*(1, 2), **{'z': 3}) 第二步:index(1, 2, z=3)
    wrapper(1, z=3, y=2)  # 第一步:wrapper(*(1, ), **{'z': 3, 'y': 2}) 第二步:index(1, y=2, z=3)
    wrapper(y=2, z=3, x=1)  # 第一步:wrapper(*(), **{'y': 2, 'z': 3, 'x': 1}) 第二步:index(y=2, z=3, x=1)
    # wrapper([1, 2, 3])  # 报错:第一步:wrapper(*([1, 2, 3]), **{}) 第二步:index([1, 2, 3])
    wrapper(*[1, 2, 3])  # 第一步:wrapper(1, 2, 3) 第二步:wrapper(*(1, 2, 3), **{}) 第三步: index(1, 2, 3)
    wrapper(*{1: None, 2: None, 3: None})  # 第一步:wrapper(1, 2, 3) 第二步:wrapper(*(1, 2, 3), **{}) 第三步: index(1, 2, 3)
    wrapper(**{'x': 1, 'y': 2, 'z': 3})  # 第一步:wrapper(x=1, y=2, z=3) 第二步:wrapper(*(), **{'x': 1, 'y': 2, 'z': 3}) 第三步: index(x=1, y=2, z=3)
    wrapper(**{'y': 2, 'z': 3, 'x': 1})  # 第一步:wrapper(y=2, z=3, x=1) 第二步:wrapper(*(), **{'y': 2, 'z': 3, 'x': 1}) 第三步: index(y=2, z=3, x=1)
    wrapper(*[1], **{'y': 2, 'z': 3})  # 第一步:wrapper(1, y=2, z=3) 第二步:wrapper(*(1, ), **{'y': 2, 'z': 3}) 第三步: index(1, y=2, z=3)
    wrapper(*[1], *{2: None, 3: None})  # 第一步:wrapper(1, y=2, z=3) 第二步:wrapper(*(1, ), **{'y': 2, 'z': 3}) 第三步: index(1, y=2, z=3)
    wrapper('1', *{2: None}, z=3)  # 第一步:wrapper(1, 2, z=3) 第二步:wrapper(*(1, 2), **{'z': 3}) 第三步: index(1, y=2, z=3)
    wrapper(*{1}, *{2: None}, z=3)  # 第一步:wrapper(1, 2, z=3) 第二步:wrapper(*(1, 2), **{'z': 3}) 第三步: index(1, 2, z=3)
    wrapper(*(1,), *'23')   # 第一步:wrapper(1, 2, 3) 第二步:wrapper(*(1, 2, 3), **{}) 第三步: index(1, 2, 3)
    

五、总结:***什么时候使用?

  1. 当一个函数中包裹着另一个函数,我们通过外面的函数名调用里面被包裹的函数。

    • 用在外层函数的参数中

    • 用在内层函数的调用中

  2. 或者为了增加函数代码的可扩展性,函数参数冗余的问题,我们使用***的形参的形式。

规则总结:

  1. 定义函数时:看到*args,就把args看成实参传值溢出以后的元组。看到** kwargs,就把kwargs看成实参传值溢出以后的字典

  2. 调用函数时: 看到*,就把它后面的对象当作位置实参传参时的形式。看到**,就把它后面的对象当作关键字实参传参时的形式。

  3. 如果需要调用外层函数控制给内层函数传值,使用*args **kwargs的形式的参数。

  4. 调用外层函数传的值,要遵守内层函数定义时的参数传参规则。

使用总结:

只看被外层函数包裹的内层函数定义时参数的规则。调用外层函数传什么值,内层函数调用就接收什么值。

六、命名关键字参数(了解)

介绍:在定义函数时,在***之间后定义的形参,称之为命名关键字形参。

特点:命名关键字实参必须按照key=value的形式为其传值。

def func(x,y=1,*args,a,b,**kwargs): # a,b都称之为命名关键字形参
    print(x)    #1
    print(y)    #2
    print(y)    #2
    print(args) #(3, 4, 5, 6, 7)
    print(a)    #111
    print(b)    #222
    print(kwargs)   
func(1,2,3,4,5,6,7,a=111,b=222,c=333)

区分命名关键字参数的默认值与默认形参:命令关键字后面的参数设置默认值,只是仅仅的设置默认值,没有位置形参与默认形参的顺序位置之分。默认形参则必须跟在位置形参之后。

def func(x,y=1,*args,a=666,b,**kwargs):
    print(x) #1
    print(y) #2
    print(args) #(3, 4, 5, 6, 7)
    print(a) #666
    print(b)    #222
    print(kwargs) #{'c': 333}
func(1,2,3,4,5,6,7,b=222,c=333)

七、组合使用(了解)

综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args、命名关键字参数、**kwargs

可变参数*args与关键字参数** kwargs通常是组合在一起使用的,如果一个函数的形参为*args**kwargs,那么代表该函数可以接收任何形式、任意长度的参数

def wrapper(*args,**kwargs):
     pass

形参组合使用顺序:位置形参、默认形参、*args(可变长度的位置行形参)、命名关键字形参、**kwargs(可变长度的关键字形参)

def func(x, y=222, *args, z, **kwargs):
    print(x)  # 1
    print(y)  # 2,这里默认参数失去了意义
    print(args)  # (2, )
    print(z)  # 4
    print(kwargs)  # {'a': 5, 'b' 6}
func(1, 2, 3, z=4, a=5, b=6)  
​

实参组合使用顺序:位置实参、关键字实参

def func(x, y, z, a, b, c):
    print(x)  # 111
    print(y)  # 222
    print(z)  # 333
    print(a)  # 444
    print(b)  # 555
    print(c)  # 666
func(111, *[222, 333], a=444, **{'b': 555, 'c': 666})
func(111,  222, 333, a=444, c=666, b=555)
func(*[111, 222], 333, **{'b': 555, 'c': 666}, a=444)
	
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贾维斯Echo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值