(小甲鱼python)函数笔记合集三 函数(III)总结 函数的收集参数*args **args 解包参数详解

一、基础复习

  1. 函数的基本用法 创建和调用函数 函数的形参与实参等等
  2. 函数的几种参数 位置参数、关键字参数、默认参数等

二、函数的收集参数

1.引言
函数有时不知道用户想传入多少个参数,而print()是支持参数可多可少的函数

>>> print("小甲鱼")
小甲鱼
>>> print("小甲鱼","爱","编程")  #打印三个参数
小甲鱼 爱 编程

2.收集参数将参数打包为元祖
收集参数:形参的名字前面加上一个星号就行了。

( * args) 称之为Non-keyword Variable Arguments 无关键字参数,一个*为参数收集器,类型为元祖类型

举例如下:

>>> def myfunc(*args):   #用*args表示收集参数
	print("有{}个参数。".format(len(args)))   #字符串的format方法
	print("第2个参数是:{}".format(args[1]))

>>> myfunc("小甲鱼","中国")
有2个参数。
第2个参数是:中国
>>> 
>>> myfunc(1,2,3,4,5)    
有5个参数。
第2个参数是:2
>>> 

打印形参,收集参数打印出来是元祖,而元祖具有打包和解包的能力

>>> def myfunc(*args):
	print(args)

>>> myfunc(1,2,3,4,5)     
(1, 2, 3, 4, 5)    #元祖
>>> 

函数可以同时返回多个值(前几节讲过)

>>> def myfunc():
	return 1,2,3

>>> myfunc()  
(1, 2, 3)      #返回值以元祖形式打印
>>> x,y,z=myfunc()   #对拿到的返回值解包
>>> x
1
>>> y
2
>>> z
3
>>> 

收集参数*args后面还有其他参数,就应该使用使用关键字参数来指定后面的参数

>>> def myfunc(*args):
	print(type(args))

>>> myfunc(1,2,3,4,5)    #收集参数*args类型为元祖

>>> 
>>> def myfunc(*args,a,b):  
	print(args,a,b)
>>> myfunc(1,2,3,4,5)  #报错,4,5应使用关键字参数
Traceback (most recent call last):
  File "", line 1, in 
    myfunc(1,2,3,4,5)
TypeError: myfunc() missing 2 required keyword-only arguments: 'a' and 'b'
>>> 
>>> myfunc(1,2,3,a=4,b=5)  #正确写法,关键字参数a=4,b=5
(1, 2, 3) 4 5

只能使用关键字参数不能使用位置参数(上一讲讲过函数的几种参数 位置参数、关键字参数、默认参数等)

>>> def abc(a,*,b,c):      # *后只能用关键字参数
	print(a,b,c)

>>> abc(1,2,3)   #需要1个位置参数,b,c也就是2和3需要使用关键字参数。
Traceback (most recent call last):
  File "", line 1, in 
    abc(1,2,3)
TypeError: abc() takes 1 positional argument but 3 were given
>>> 
>>> abc(1,b=2,c=3)  #正确写法
1 2 3

3.收集参数将参数打包为字典

(* args)称之为Non-keyword Variable Arguments 无关键字参数,一个星号*为参数收集器,类型为元祖类型
(**kwarge) 称之为keyword Variable Arguments,有关键字参数,两个星号 ** 为字典形式的收集参数

举例如下:
字典是以键值对出现的,如a=1,等号左边是键,右边是值。

>>> def myfunc(**kwargs):
	print(kwargs)

>>> myfunc(a=1,b=2,c=3)    #关键字参数
{'a': 1, 'b': 2, 'c': 3}
>>> 
>>> def myfunc(a,*b,**c):     #两种收集参数方法混合使用,
	print(a,b,c)

>>> myfunc(1,2,3,4,x=5,y=6)   #1为位置参数,2,3,4为元祖,5,6为字典
1 (2, 3, 4) {'x': 5, 'y': 6}

字符串的format方法同时使用一个星号和两个星号作为收集参数的情况

>>> help(str.format)
Help on method_descriptor:

format(...)
    S.format(*args, **kwargs) -> str
    
    Return a formatted version of S, using substitutions from args and kwargs.
    The substitutions are identified by braces ('{' and '}').

>>> 

4.解包参数
一个星号和两个星号在函数上也有使用,在形参上使用我们称为参数的打包,在实参上使用则起到了相反的结果。
一个星号* 实际参数将元祖解包:

>>> args=(1,2,3,4)
>>> def myfunc(a,b,c,d):
	print(a,b,c,d)

>>> myfunc(args)   #报错,需要4个参数但只传入一个参数
Traceback (most recent call last):
  File "", line 1, in 
    myfunc(args)
TypeError: myfunc() missing 3 required positional arguments: 'b', 'c', and 'd'
>>> 
>>> myfunc(*args)   #对参数的解包,args不在是一个元祖,它被解包成1,2,3,4传递到a,b,c,d四个形参里面
1 2 3 4

两个星号**实际参数将字典解包成关键字参数

>>> kwargs={'a':1,'b':2,'c':3,'d':4}
>>> myfunc(**kwargs)   #字典解包
1 2 3 4
>>> 

课后题:

  1. 在函数定义中,带一个星号的形参(如 def func(*x))和带两个星号的形参(如 def func(**x))有什么区别?
    答:都是收集参数,但是打包方式不同。一个星号是将收集到的参数打包为元组的形式;两个星号是将收集到的参数打包为字典的形式。

2. 请问下面代码会打印什么呢?

>>> def func(a, b=4, c=5):
...     print(a, b, c)
...        
>>> func(1, 2)
>>> # 请问这里会打印什么内容?

答:

>>> func(1, 2)
1 2 5

解析:1 和 2 作为位置参数传递给了形参 a 和 b,并且 c 在调用中被忽略了,从而使用默认值 5。
3. 请问下面代码会打印什么呢?

>>> def func(x, *y, z=3):
...     print(x, y, z)
...
>>> func(1, 1, 2, 3, 5)
>>> # 请问这里会打印什么内容?

答:

>>> func(1, 1, 2, 3, 5)
1 (1, 2, 3, 5) 3

解析:由于形参 y 是定义为收集参数,所以除了第一个实参 1 给到 x;其它的实参(1、2、3、5)都给到了 y;z 就只能使用默认值 3,如果想要给 z 赋值,需要使用关键字参数才行。
4.请问下面代码会打印什么呢?

>>> def func(x, *y, **z):
...     print(x, y, z)
...
>>> func(1, 2, 3, 4, y=5)
>>> # 请问这里会打印什么内容?

答:

>>> func(1, 2, 3, 4, y=5)
1 (2, 3, 4) {'y': 5}

解析:实参 1 传给第一个位置参数 x;接着的 2,3,4 传给元组收集参数 y;最后一个 y=5 传给字典收集参数 z。
5.请问下面代码会打印什么呢?

>>> def func(x, *y, **z):
...     print(x, y, z)
...
>>> func(1, 2, x=3, y=4, z=5)
>>> # 请问这里会打印什么内容?

答:会报错。

>>> func(1, 2, x=3, y=4, z=5)
Traceback (most recent call last):
  File "", line 1, in 
    func(1, 2, x=3, y=4, z=5)
TypeError: func() got multiple values for argument 'x'

解析:虽然说映射形式的多个参数会被字典形的收集参数统一收集,但这里由于 x 是第一个形参的名字,从而产生冲突(Python 搞不懂 x=3 的含义是要通过关键字参数赋值,还是被收集参数 z 获取……所以注意代码一定不要有二义性,否则都会出错。
6.请问下面代码会打印什么呢?

>>> def func(x, y, z=3):
...     print(x, y, z)
...
>>> func((1, 2), *(3, 4))
>>> # 请问这里会打印什么内容?

答:

>>> func((1, 2), *(3, 4))
(1, 2) 3 4

解析:第一个实参 (1, 2) 是以元组的形式传递,所以作为整个传递给形参 x;第二个参数 * (3, 4) 虽说也是元组,但作为实参前面带个星号(*),表示解包操作,会将 3 和 4 拆开后再分别传递给形参 y 和 z。

题目来自小甲鱼函数(III)

你可能感兴趣的:(python,小甲鱼课程笔记,python)