Python中的*号使用场景与区别
直白点的区别就是:函数调用时,*和都是解包,函数定义时是将传过来的参数进行打包**
星号的使用场景有两个
- 在【函数定义】和【函数调用】的时候使用
- 作为接收序列参数:a,*b=1,2,3,4
这里主要讲第一种
函数定义时.
- args: 接收传递过来的序列引用,读取引用中的位置参数,【打包】成一个元祖,将引用指向args
- kwargs: 接收传递过来的字典引用,读取引用中的关键字参数,【打包】成一个字典,将引用指向kwargs
注意:如果参数列表有*args,**kwargs,但是没有接收到参数,那么输出args就是一个空元祖,kwargs是个空字典,当参数args只有一个时,那么输出的元祖就是(1,)后面有一个,代表是个元祖
函数调用时
- *args 和**kwargs:传递的是序列的引用,获取引用中的值,然后作为实参传递
- 注意事项:由于是引用,会更改内部的值,如图
场景1:函数定义与调用都不使用*号
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(tmp):
print(tmp)
print(*tmp) # 这里面和上面一样序列解包
f(a) # 直接传列表引用作为参数
f(b) # 与函数外面保持一致
f(c) # 与函数外面保持一致
[1, 2, 3, 4]
1 2 3 4
(7, 8, 9, 10)
7 8 9 10
{'age': 18, 'name': 'vdx'}
age name
提问:既然能直接定义一个变量接收序列的引用,为什么还需要用*和**?
思考:虽然效果是一样的,但是有些情况不是直接传列表,而是单个单个的位置参数传递,比如fun(1,2,3)
场景2:函数定义时:使用*号
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(*tmp):
print(tmp)
print(*tmp)
f(a) # 直接传列表引用作为参数,注意:函数能直接更改原件,如果想弄副本,加上*
f(b)
f(c)
(1, 2, 3, 4)
1 2 3 4
((7, 8, 9, 10),)
(7, 8, 9, 10)
({'age': 18, 'name': 'vdx'},)
{'age': 18, 'name': 'vdx'}
场景3:函数定义时:使用*号
a=[1,2,3,4]
b=(7,8,9,10)
c={'age':18,'name':'vdx'}
def f(**tmp):
print(tmp)
f(**c) # 与函数外面保持一致
{'age': 18, 'name': 'vdx'}
提示:对字典使用*,能够取出里面的key
为什么我们不能print(**kwargs),却能print(*args)
不是说**不能解包,而是print不支持输出关键字参数
区别归纳
1.之前赋值时,*可以用来接收多余的对象值,那种用法与函数中的用法不一样,切记混合使用,【一个是赋值时接收多余的参数,一个是在函数中传递,接收多个值是使用】
例题:
# 二、请写出下列代码的运行结果
def f(str1, *args, **kwargs):
print(str1, args, kwargs)
l = [1, 2, 3]
t = [4, 5, 6]
d = {"a": 7, "b": 8, "c": 9}
f(1, 2)
f(1, 2, 3, "python")
f("python", a=1, b=2, c=3)
f("python", l, d)
f("python", *t)
f('python', *l, **d)
f("python", q="winning", **d)
print('-' * 90)