参数打包,解包

Python中的*号使用场景与区别

直白点的区别就是:函数调用时,*和都是解包,函数定义时是将传过来的参数进行打包**

星号的使用场景有两个

  1. 在【函数定义】和【函数调用】的时候使用
  2. 作为接收序列参数: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)
posted @ 2021-07-03 21:20  中州韵  阅读(230)  评论(0编辑  收藏  举报