最常见的是:在函数中,用 * args和**kwargs表示可变参数和仅使用key = value的参数。另外最近碰到了一个,用于unpacking dictionary的*号用法。下面讨论一下:
- *用于展开list、tuple、dict,直接访问里面的元素
Eg:
def main():
a = [1,2,3,4]
b = (1,2,3,4)
c = {'key1': 1, 'key2': 2}
print(*a, end = '\t')
print(a)
print(*b, end = '\t')
print(b)
print(*c, end = '\t')
print(c)
if __name__ == '__main__':
main()
结果为:
1 2 3 4 [1, 2, 3, 4]
1 2 3 4 (1, 2, 3, 4)
key1 key2 {'key1': 1, 'key2': 2}
和直接print对比很明显可以发现,这里的“展开”字典,实际上只是访问了字典的key而没有访问字典的value
这个用法甚至允许不同类型的变量合并在一起,比如:
a = [1,2,3,4]
b = (1,2,3,4)
c = {'key1': 1, 'key2': 2}
print(*a,*b,*c)
1 2 3 4 1 2 3 4 key1 key2
因为传入函数的参数是展开了的参数,所以实际上前面的代码,传给print的参数是4个,后面的代码传给print的参数是8个,这一点可以通过自己定义函数很明显体会到:
def f1(a,b,c,d):
print(a,b,c,d, end = '\t')
f1(*a)
f1(*a,*b)
运行结果是:
1 2 3 4
TypeError: f1() takes 4 positional arguments but 8 were given
那么print是怎么做到既可以接受4个参数,又可以接受8个参数的呢?看下面:
- *args传递可变长参数、**kwargs传递使用key的可变长参数
Eg:
def f1(*args):
for a in args:
print(a, end = '')
print()
def f2(**kwargs):
for k,v in kwargs.items():
print(k,v)
def main():
f1(1)
f1(1,2,3)
f2(name = 'name_name', key = 'key_key')
f2(name = 'key')
if __name__ == "__main__":
main()
输出结果为:
1
123
name name_name
key key_key
name key
回答1最后提出的问题,print函数的定义,肯定是print(*args)这样的形式。2个结合一下:
def f1(*args):
for a in args:
print(a, end = '')
print()
def f2(**kwargs):
for k,v in kwargs.items():
print(k,v, end = '')
print()
print(kwargs)
def main():
b = [1,2,3,4]
f1(b)
f1(*b)
a = {"name": 'name_name', "key": 'key_key'}
f2(**a)
if __name__ == "__main__":
main()
结果为:
[1, 2, 3, 4]
1234
name name_namekey key_key
{'name': 'name_name', 'key': 'key_key'}
第一行输出[1, 2, 3, 4]
是因为把b当作1个参数输入f1了,所以执行print(a, end = '')
这一句,没有换行,循环1次就退出来,执行print()
再换行
第二行输出1234,是因为b的4个元素作为4个参数输入f1,所以循环4次,循环内print不换行,所以1234是紧邻的,循环后才换行
第三行输出,是因为**a展开了a的元素,把2个key-value对作为参数输入f2,所以循环执行2次,循环内print不换行,因此name_namekey
就是紧邻着的,循环结束后换行,所以第四行输出执行print(kwargs)
,实际上就是直接打印字典了。
可以看到在f2函数里面,kwargs实际上就是输入的字典,但是为什么要写**kwargs,而不直接写f2(input_dict)呢?因为f2(**kwargs)的输入参数可以是多个字典,但f2(input_dict)只能用1个字典作为输入。
最后总结一下:
- *符号可以用作展开list、tuple、dict里面的元素(字典只能展开key)
- 函数定义时,如果输入参数用了*args,**kwargs,表示输入参数是可变长度的,前者是普通的可变长度参数,后者是key-value对形式的可变长度参数。
- 上面2点结合,在函数内就可以访问多个输入的参数合并到一起的变量了。
参考链接
https://treyhunner.com/2018/10/asterisks-in-python-what-they-are-and-how-to-use-them/
https://stackoverflow.com/questions/36901/what-does-double-star-asterisk-and-star-asterisk-do-for-parameters