从零开始学Python-Day17-函数参数(2)

Python零基础 木人张 3年前 (2020-03-22) 849次浏览 0个评论 扫描二维码
文章目录[隐藏]

上一节说了参数位置和默认参数,这一节着重说可变参数和关键字参数

可变参数

可变参数就是传入的参数个数是可变的,可以任意个参数,包括0个参数。
我们以计算a2 + b2 + c2 + ……为例
要定义这个函数,我们可以把需要传入的参数以一个list或者tuple传入,定义如下,这里我们用到了for循环,从list或tuple中循环取值,执行命令:

>>> def f(num):
	sum=0
	for n in num:
		sum=sum+n*n
	return sum

>>> f((1,2,3))
14
>>> f([2,3,4])
29
>>> f(1,2,3)
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    f(1,2,3)
TypeError: f() takes 1 positional argument but 3 were given

我们看到传入的参数为list和tuple时可以很好的完成任务,但是我们想简单点直接写一组数字就报错了。这个时候就需要用到可变参数。在定义时,num前加*号,这样函数会把传入的参数按一个tuple接收:

>>> def f(*num):
	sum=0
	for n in num:
		sum=sum+n*n
	return sum

>>> f(1,2,3)
14
>>> f(2,3,4)
29
>>> 

那么如果说我们已经有一个list或者tuple,想对整个list或tiple调用函数f该如何调用呢,一种方法是直接用list的定位来完成参数传入:

>>> l=[3,4,5]
>>> f(l[0],l[1],l[2])
50
>>> s=(3,4,5)
>>> f(s[0],s[1],s[2])
50

这样操作显然有些麻烦,如果list里内容太多也一样写不过来,这时可以用第二种方法,可以直接在函数调用时,在list或者tuple前面加*进行传参,如下:

>>> f(*l)
50
>>> f(*s)
50

关键字参数

关键词参数允许函数传入0个或多个含有参数名的参数,在函数内部组装为一个字典dict

>>> def person(name,age,**other):
	print('name:',name,'age:',age,'other',other)
>>> person('张三',35)
name: 张三 age: 35 other {}
>>> person('李四',36,city='北京')
name: 李四 age: 36 other {'city': '北京'}
>>> person('王五',40,city='北京',site='www.woodmangzhang.com')
name: 王五 age: 40 other {'city': '北京', 'site': 'www.woodmangzhang.com'}

上面这个示例有点像我们在用户注册时,有些是必填信息,有些是非必填项,但是如果用户愿意提交就都可以提交。
关键词参数也可以调用已经组装好的dict来完成传参,如下:

>>> others={'city':'北京','site':'www.woodmangzhang.com'}
>>> person('赵六',29,**others)
name: 赵六 age: 29 other {'city': '北京', 'site': 'www.woodmangzhang.com'}

可变参数是一个*,关键词参数是两个*,在定义和调用时都是一样的用法,只不过一个是list或tuple,一个是dict。上面的例子中注意others是一个外部的dict,函数内部的other只是从外部的others取值,内部other的改变并不影响外部的others。

命名关键词参数

那用了关键词参数,使用者不是随便传参数内容进来,这就需要函数内部做检查,仍然以上面的问题为例,我们要检查是否有city和site:

>>> def person(name,age,**other):
	if 'city' in other:
		pass
	if 'site' in other:
		pass
	print(name,age,other)

>>> person('张三',15,city='北京',site='www.woodmanzhang.com')
张三 15 {'city': '北京', 'site': 'www.woodmanzhang.com'}
>>> person('张三',15,city='北京',site='www.woodmanzhang.com',homeadd='中关村壹号')
张三 15 {'city': '北京', 'site': 'www.woodmanzhang.com', 'homeadd': '中关村壹号'}

可以看到调用者依然可以随意传入数据,如果我们要限制只接受city和site作为关键词参数,可以用*,关键词1,关键词2表示,也就是命名关键词:

>>> def person(name,age,*,city,site):
	print(name,age,city,site)

>>> person('张三',21,city='北京',site='www.woodmanzhang.com')
张三 21 北京 www.woodmanzhang.com
>>> person('张三',21,city='北京',site='www.woodmanzhang.com',homeadd='中关村壹号')
Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    person('张三',21,city='北京',site='www.woodmanzhang.com',homeadd='中关村壹号')
TypeError: person() got an unexpected keyword argument 'homeadd'
>>> person('木人张',35)
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    person('木人张',35)
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'site'
>>> person('木人张',35,'北京','www.woodmangzhang.com')
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    person('木人张',35,'北京','www.woodmangzhang.com')
TypeError: person() takes 2 positional arguments but 4 were given

可见,当设定了命名关键词参数,对应的参数就成了必选参数,当我们多输入和少输入命名关键词参数时都会报错;对于命名关键词参数,不按关键词传入也一样会报错!因为没有加关键词传入,函数理解为传入了四个位置参数,但定义函数时指指定了2个位置参数。
而如果函数中已经有了一个可变参数,那么后面跟着的命名关键词参数就都不再需要*来分隔:

>>> def person(name,age,*s,city,site):
	print(name,age,s,city,site)

命名关键词还可以设定缺省默认值,从而简化调用时的传入,如下有了默认值,我们传参时可以不传入这一项:

>>> def person(name,age,*,city='北京',site):
	print(name,age,city,site)

>>> person('张三',18,site='woodmanzhang.com')
张三 18 北京 woodmanzhang.com

需要注意的是,*的区隔必须有,可以是一个可变参数,或者没有可变参数用*, 如果没有*这一标识,程序会认为需要传入的都是位置参数,无法识别关键词参数。
另外,关键词参数是可以调换顺序的,这也是它跟位置参数的一个区别,如下:

>>> person('张三',18,site='woodmanzhang.com',city='上海')
张三 18 上海 woodmanzhang.com

参数组合

必须参数、默认参数、可变参数、命名关键字参数、关键字参数可以组合使用,即为参数组合,注意参数定义的顺序,也要按这一顺序。

>>> def f1(a,b,c=0,*args,**kw):
	print(a,b,c,args,kw)

>>> def f2(a,b,c=0,*,d,**kw):
	print(a,b,c,d,kw)

>>> f1(1,2,3)
1 2 3 () {}
>>> f2(1,2,3)
>>> f2(1,2,3,d=4,n=5)
1 2 3 4 {'n': 5}
>>> f1(1,2,3,('a','b'),'nono')
1 2 3 (('a', 'b'), 'nono') {}
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> args=(1,2,3,4)
>>> kw={'d':99,'e':100}
>>> f1(*args,**kw)
1 2 3 (4,) {'d': 99, 'e': 100}
>>> args=(1,2,3)
>>> f2(*args,**kw)
1 2 3 99 {'e': 100}
>>> args=[1,2,3]
>>> f2(*args,**kw)
1 2 3 99 {'e': 100}

函数调用时,不论是手动传入的参数,还是list或者tuple和dict,都可以给函数传参调用。


木人张,版权所有丨如未注明 , 均为原创,禁止转载。
喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址