day3-函数的非固定参数
一、概述
在上一篇博客中我已经写了,位置参数和关键字参数,下面我们来谈谈默认参数和参数组
二、默认参数
默认参数指的是,我们在传参之前,先给参数制定一个默认的值。当我们调用函数时,默认参数是非必须传递的。
def test(x,y=2): print(x) print(y) print("-----data1----") test(1) #没有给默认参数传值 print("-----data2----") test(1,3) #给默认参数传位置参数 print("-----data3----") test(1,y=3) #给默认参数传关键字参数 #输出 -----data1---- 1 2 -----data2---- 1 3 -----data3---- 1 3
默认参数用途:
- 安装默认软件(def test(x,soft=True))
- 传递一下默认的值(定义mysql的默认端口号:def count(host,port=3306))
三、参数组
之前我们传参数,都是传一个固定参数,不能多也不能少,但是如果说我们需要非固定参数怎么办呢?好吧,于是就衍生出了,以下两种传参方式:
- 非固定位置参数传参(*args)
- 非固定关键字传参(**kwargs)
下面我们就来说说这两种方式传参:
1、非固定位置参数传参
①功能:接收N个位置参数,转换成元组的形式。
②定义,代码如下:
def test(*args): #形参必须以*开头,args参数名随便定义,但是最好按规范来,定义成args print(args) test(1,2,3,4,5) #输入多个位置参数 #输出 (1, 2, 3, 4, 5) #多个参数转换成元组
这边不禁的有个疑问,你这是传入的都是N个位置参数,那我要传入一整个列表咋办,我要完全的获取这个列表的值。
③传入列表
def test(*args): print(args) print("-------data1-----") test() #如果什么都不传入的话,则输出空元组 print("-------data2-----") test(*[1,2,3,4,5]) #如果在传入的列表的前面加*,输出的args = tuple([1,2,3,4,5]) print("-------data3-----") test([1,2,3,4,5]) #如果再传入的列表前不加*,则列表被当做单个位置参数,所以输出的结果是元组中的一个元素 #输出 -------data1----- () -------data2----- (1, 2, 3, 4, 5) -------data3----- ([1, 2, 3, 4, 5],)
④位置参数和非固定位置参数
def test(x,*args): print(x) #位置参数 print(args) #非固定参数 test(1,2,3,4,5,6) #输出 1 (2, 3, 4, 5, 6)
从上面看出,第1个参数,被当做位置参数,剩下的被当做非固定位置参数。
⑤关键字和非固定位置参数
def test(x,*args): print(x) print(args) test(x=1,2,3,4,5,6) #输出 File "D:/PycharmProjects/pyhomework/day3/非固定参数/非关键字参数.py", line 21 test(x=1,2,3,4,5,6) ^ SyntaxError: positional argument follows keyword argument #位置参数在关键字参数后面
很显然报错了,因为x=1是关键字参数,*args是位置参数,而关键字参数不能再位置参数前面的,所以报错。
2、非固定关键字传参
①功能:把N个关键字参数,转换成字典形式
②定义,代码如下:
def test(**kwargs): #形参必须以**开头,kwargs参数名随便定义,但是最好按规范来,定义成kwargs print(kwargs) test(name="qigao",age=18) #传入多个关键字参数 #输出 {'name': 'qigao', 'age': 18} #多个关键字参数转换成字典
③传入字典
def test(**kwargs): print(kwargs) test(**{"name":"qigao","age":18}) #传入字典时,一定要在字典前面加**,否则就会报错 #输出 {'name': 'qigao', 'age': 18}
然而,有些小伙伴说,我就不信,难道不加**,就会报错,那为啥非固定位置参数不加*,为啥就不报错呐?下面我们就用事实说话,代码如下:
def test(**kwargs): print(kwargs) test({"name":"qigao","age":18}) #输出 Traceback (most recent call last): File "D:/PycharmProjects/pyhomework/day3/非固定参数/非固定关键字参数.py", line 9, in <module> test({"name":"qigao","age":18}) TypeError: test() takes 0 positional arguments but 1 was given #报类型错误,传入的是位置参数
因为传入的字典被当做位置参数,所以被报类型错误,所以小伙伴们千万要记住:传字典,加**
④配合位置参数使用
def test(name,**kwargs): print(name) print(kwargs) print("------data1-----") test("qigao") #1个位置参数 print("------data2------") test("qigao",age=18,sex="M") #1个位置参数,两个关键字参数 print("------data3------") test(name="qigao",age=18,sex="M") #3个关键字参数 #输出 ------data1----- qigao #输出1个位置参数 {} #没有输入关键字参数,所以输出空字典 ------data2------ qigao #第1个位置参数 {'age': 18, 'sex': 'M'} #剩下关键字参数,转换成1个字典 ------data3------ qigao #第1个关键字参数 {'age': 18, 'sex': 'M'} #剩下的关键字参数,转换成1个字典
⑤位置参数、关键字和非固定关键字参数
提示:参数组一定要往最后放
def test(name,age=18,**kwargs): print(name) print(age) print(kwargs) print("----------data1--------") test("qigao",sex='M',hobby='tesl') print("----------data2--------") test("qigao",34,sex='M',hobby='tesl') print("----------data3--------") test("qigao",sex='M',hobby='tesl',age=34) #age关键字参数放到最后,也可以的 #输出 ----------data1-------- qigao 18 #不传,显示默认参数 {'sex': 'M', 'hobby': 'tesl'} ----------data2-------- qigao 34 #传位置参数 {'sex': 'M', 'hobby': 'tesl'} ----------data3-------- qigao 34 #关键字参数,放在前后并没有影响 {'sex': 'M', 'hobby': 'tesl'}
注:就是说,如果遇到一个关键字传参和非固定关键字传参,前后放的位置是不影响传参的,但是我们一般还是按顺序来。
⑥位置参数、关键字参数、非固定位置参数和非固定关键字参数
def test(name,age=18,*args,**kwargs): print(name) print(age) print(args) print(kwargs) print("-------第1种传参--------") test("qigao",19,1,2,3,4,sex="m",hobby="tesla") print("-------第2种传参--------") test("qigao",19,*[1,2,3,4],**{'sex':"m",'hobby':"tesla"}) #输出 -------第1种传参-------- qigao #传name位置参数 19 #给age传位置参数 (1, 2, 3, 4) #非固定位置参数,以转换成元组 {'sex': 'm', 'hobby': 'tesla'} # 非固定关键字参数,转换成字典 -------第2种传参--------- qigao 19 (1, 2, 3, 4) #以列表的形式传入,在列表前加* {'sex': 'm', 'hobby': 'tesla'} #以字典的形式传入,在字典前加**
那么问题来了,上面的age传参传的是位置参数,那我能不能传关键字参数呐?现在我们就来看看,代码如下:
def test(name,age=18,*args,**kwargs): print(name) print(age) print(args) print(kwargs) test("qigao",age=19,1,2,3,4,sex="m",hobby="tesla") #输出 File "D:/PycharmProjects/pyhomework/day3/非固定参数/非固定关键字参数.py", line 55 test("qigao",age=19,1,2,3,4,sex="m",hobby="tesla") ^ SyntaxError: positional argument follows keyword argument #语法错误,位置参数在关键字参数前面
看来是不可以的,为什么?因为age=19是关键字参数,而后面的*args是非固定位置参数,说白了不管*args传入几个字,它的本质都是位置参数,上面我们提到关键字参数是不能再位置参数的前面,所以报错了。
看来上面的情况是不可以的,那能不能非固定关键字参数在非固定位置参数前面呢?来,我们带着疑问一起来试一下。代码如下:
def test(name,age=18,*args,**kwargs): print(name) print(age) print(args) print(kwargs) test("qigao",19,sex="m",hobby="tesla",1,2,3,4,5) #输出 File "D:/PycharmProjects/pyhomework/day3/非固定参数/非固定关键字参数.py", line 57 test("qigao",19,sex="m",hobby="tesla",1,2,3,4,5) ^ SyntaxError: positional argument follows keyword argument #语法错误,关键字参数在位置参数前面
我擦咧,也是不可以的,经我仔细研究发现,非固定关键字参数,本质也是关键字参数,是不能放在非固定位置参数的前面的。
四、总结
- 参数分为位置参数、关键字参数、默认参数、非固定位置参数和非固定关键字参数
- 位置参数之前传参,位置是不能调换的,多一个或者少一个参数都是不可以的。
- 关键字参数是不能放在位置参数前面的。
- 函数传参的位置一次是,位置参数,默认参数、非固定位置参数、非固定关键字参数(def test(name,age=18,*args,**kwargs))
- 关键字传参,可以不用考虑位置的前后问题