前言

*参数与**参数是Python参数中的重点知识,他们都被称为可变参数(任意参数),我们经常会在代码中看到*args、**kwargs

作为函数定义时:

1、*参数收集所有未匹配的位置参数组成一个tuple对象,局部变量args指向此tuple对象

2、**参数收集所有未匹配的关键字参数组成一个dict对象,局部变量kwargs指向此dict对象

def temp(*args,**kwargs):pass

作为函数调用时:

1、*参数用于解包tuple对象的每个元素,作为一个一个的位置参数传入到函数中

2、**参数用于解包dict对象的每个元素,作为一个一个的关键字参数传入到函数中

my_tuple = ("wang","yuan","wai")temp(*my_tuple)
#---等同于---#
temp("wangyuan","yuan","wai")
my_dict = {"name":"wangyuanwai","age":32}temp(**my_dict)
#----等同于----#
temp(name="wangyuanwai",age=32)

这些基本概念暂时不理解很正常,完全理解需要一个过程……接下来的几个例子会说明这些概念,希望可以对每一位学习Python的同学带来帮助!!

包含两个位置参数的函数print_str

def print_str(first, second):print(first)print(second)

只传1个参数调用print_str()函数,会发生什么呢?

print_str("hello")

输出结果:

TypeError: print_str() takes exactly 2 arguments (1 given)

TypeError:解释器在控制台告知print_str()函数需要2个参数,而你只为print_str()函数传入了1个参数!

思考:怎么修改print_str()函数为即可接受一个参数、也可接受两个参数、甚者接受数量不定的更多参数呢?

修改print_str()函数可接受一个参数、也可接受数量不定的参数

将print_str()函数的最后一个参数修改为可变参数*second

def print_str(first, *second):print(first)print(second)

此时我们再传一个参数调用print_str()函数,看看这次发生什么?

print_str("hello")

输出结果:

hello
()

这次不再报错,传入的第一个字符串参数"hello"打印出来了,没有传入参数的*second则打印的是一个tuple对象的字符串表示形式,即一个括号"()"  。 注意:()表示含有0个元素的tuple对象!

思考:为什么second变量变成一个tuple对象了?我们继续向下学习!

再做一个实验,为print_str()函数传入四个参数…会发生什么?

print_str("hello","美女","小猫","青蛙")

输出结果:

hello
('美女', '小猫', '青蛙')

第一个参数“hello”,正常打印在第一行……

第二个参数"美女",第三个参数“小猫”,第四个参数“青蛙”在函数的内部被组装进1个新的tuple对象中,而这个新的tuple对象会赋值给变量second,此时局部变量second指向了一个tuple对象

说明:函数调用时传入的参数,会按照从左到右的顺序依次在函数中使用,最左侧的参数先由位置参数first使用(匹配),剩下的所有未匹配的参数会被自动收集到1个新的tuple对象中,而局部变量second会指向这个新的tuple对象

注意:*参数只收集未匹配的位置参数

调用print_str()函数时,直接传入一个 *参数会发生什么?

numbers_strings = ("1","2","3","4","5")def print_str(first, *second):print(first)print(second)if __name__ == "__main__":print_str(*numbers_strings) #注意这里的*numbers_strings
输出结果:
1
('2', '3', '4', '5')

说明:*numbers_strings出现在函数调用时,称为解包(一个“*”字符后面紧挨着1个tuple对象),numbers_strings自身是一个tuple对象,所以也称为元组的解包,tuple中的元素解包成一个一个的位置参数传入到函数中,所以才有下面两个语句的相等性!

print_str(*numbers_strings)

等同于

print_str("1","2","3","4","5")

未定义可变参数的函数被调用时,传入*参数会发生什么呢?

numbers_strings = ("1","2")def print_str(first, second):print(first)print(second)if __name__ == "__main__":print_str(*numbers_strings)

输出结果:

12

print_str(*numbers_string)

等同于

print_str("1","2")

元组解包的过程中会将每一个元素依次放入到位置参数,这说明元组的解包功能的如下特点:

1、可以在可变参数中使用

2、也可以在未定义可变参数的函数上使用

元组解包功能是完全独立的一个功能

再次说明:*参数,出现在函数的不同的位置上时,具备不同的功能

1、当*参数出现在函数定义时,表示可变参数

2、当*参数出现在函数调用时,则表示解包功能

注意:解包tuple的时候,tuple的元素数量要与函数的位置参数总数一致

………………华丽丽分割线,接下来我们再学学**kwargs………………

函数定义中,参数名称前有两个**

def printStr(**anything):print(anything)
传入两个关键字参数调用printStr函数,看看发生什么?
printStr(first = 5, second = 100)
输出结果:
{'second': 100, 'first': 5}

打印结果为dict对象的字符串形式,为什么anything成为dict了?

说明:函数调用时,传入的关键字参数有匹配的位置参数时,则位置参数优先使用(匹配)这些关键字参数,剩余所有未使用(未匹配)的关键字参数会在函数内组装进一个dict对象中,组装后dict对象会赋值给变量名anything,此时局部变量anything指向一个dict对象

注意:**参数只收集未匹配的关键字参数

函数调用时使用字典解包功能(dict对象前加**)

def printStr(first, **dict):print(str(first) + "\n")print(dict)printDic = {"name": "tyson", "age":"99"}
printStr(100, **printDic)#等同于printStr(100, name = "tyson", age = "99") 

说明:函数调用时,在一个dict对象的前面,添加**,表示字典的解包,它会把dict对象中的每个键值对元素,依次转换为一个一个的关键字参数传入到函数中

总结

Python语法中,当*参数和**参数同时出现在函数定义的参数列表中时,说明参数列表可接受任意数量的参数,它们都统称为可变参数

函数定义时

1、*args表示可接受任意个(包含0个)位置参数,当函数调用时,所有未使用(未匹配)的位置参数会在函数内自动组装进一个tuple对象中,此tuple对象会赋值给局部变量args

2、**kwargs表示可接受任意个(包含0个)关键字参数,当函数调用时,所有未使用(未匹配)的关键字参数会在函数内组装进一个dict对象中,此dict对象会赋值给局部变量kwargs

注意:函数定义时,二者同时存在,一定需要将*args放在**kwargs之前

注意:函数定义时,二者同时存在,一定需要将*args放在**kwargs之前

注意:函数定义时,二者同时存在,一定需要将*args放在**kwargs之前

(重要的事情说三遍)

函数调用时

1、*args表示解包元组对象中的每个元素作为位置参数传入到被调用函数中

2、**kwargs表示解包字典对象中的每个元素作为关键字参数传入到被调用函数中

注意事项

1、可变参数,可以传数量不定的多个参数,包括0个参数

2、可变参数,必须定义在普通参数(也称位置参数、必选参数、选中参数等名称)以及默认值参数的后面,这是因为可变参数会收集所有【未匹配】的参数,如果将可变参数定义在前面,那么普通参数与默认值参数就无法匹配到传入的参数,因为全都收集到可变参数中了

def printStr(普通参数,默认值参数name="王员外",*参数,**参数):pass

3、*参数必须定义在**参数的前面

def printStr(普通参数,*参数,**参数):pass
4、调用包含*args参数的函数时,不要直接传入一个tuple对象,如果传入的是一个tuple对象,那么这个tuple对象只会成为未匹配的,函数内组装的tuple对象中一个元素而已。我们可以将tuple对象的元素使用元组解包语法传入,解包语法:*tuple

temp = (1,2,3,4,5)def my_first(*args):print(args)my_first(temp)  #temp只算一个参数,除非你有这个需求my_first(*temp) #OK
5、调用包含**kwargs参数的函数时,不要直接传入一个字典对象,一个字典对象只算一个参数,此时会报错,因为一个dict对象不符合关键字参数的语法规范,字典对象可以使用字典解包语法,解包语法: **dict
my_book = {"first":"小当家", "seoncd": "我是baby"}def my_blood(**kwargs):print(kwargs)my_blood(my_book)   #作为一个字典对象传入my_blood(**my_book) #一个一个的关键字参数传入
6、*参数的变量名,一般使用变量名args,只是建议,你想叫啥名都行,它只是局部变量名
7、**参数的变量名,一般使用变量名kwargs,只是建议,你想叫啥名都行,它也是个局部变量名

一个包含位置参数、默认值参数,可变参数的函数(供参考)

def my_first_blood(first_name,last_name,age=0,*args,**kwargs):print(first_name)print(last_name)print(age)for ele in args:print(ele)for key,value in kwargs.items():print(key)print(value) 

调用方式:

my_first_blood("王","员外")my_first_blood("王","员外", 32)my_first_blood("王","员外", 32, "北京", "海淀", style="开心")

一个仅传入关键字参数,导致报错的函数

def temp(say, **kwargs):print(say)print(kwargs)temp(fk=100, hello=1000)

由于位置参数say,与传入的关键字参数fk和hello均不能匹配,所以此调用会导致报错。关键字参数必须得与位置参数的名称相匹配时,才能被位置参数使用

解包功能不只是tuple、还有list、str、range

first = (1,2,3)second = [1,2,3]third = "123"fourth = range(4)print(*first)print(*second)print(*third)print(*fourth)

只要是序列类型,可迭代对象,都可以使用解包功能哦

Python之可变参数,*参数,**参数,以及传入*参数,**参数解包,*args,**kwargs的理解相关推荐

  1. Python进程池之pool.map()函数传入多参数

    一 定义与解释 对于python代码,多线程其实是个假的,因为每次计算的时候,实质上只有一个线程计算.使用多线程时,是几个线程之间切换计算,就像轮班工作一下,适合处理I/O密集型的任务. 对于pyth ...

  2. android httpget 参数,安卓通过httpget传入json参数,请求数据

    server接口如: http://127.0.0.1?param={ "Params" : { "ProjectID" : "00000010&qu ...

  3. python基础 python函数 函数概念 函数的多种参数 多种调用参数 装包 解包 函数代码块 函数的返回值

    python基础 python函数 函数概念 函数的多种参数 多种调用参数 装包 解包 函数代码块 函数的返回值 一 .函数概念 函数是根据需要,将代码打包为代码块, 每一个代码块就可以封装为一个函数 ...

  4. python全栈学习--day12(函数高级应用-带参数的装饰器,多个装饰器装饰一个函数)...

    函数的执行时,*打散 函数的定义时,*聚合 from functools import wrapsdef wrapper(f):@wraps(f)def inner(*args,**kwargs):' ...

  5. python内置函数教程_Python内置函数详解

    此文参考python文档,然后结合自己的理解,写下来,一方面方便自己,让自己好好学习,顺便回忆回忆:另一方面,让喜欢的盆友也参考一下. 经查询,3.6版本总共有68个内置函数,主要分类如下: 数学运算 ...

  6. Python的解包知识

      在Python中的代码中经常会见到 *args 和 **kwargs.args 是 arguments 的缩写,*args表示位置参数:kwargs 是 keyword arguments 的缩写 ...

  7. python中的装包与解包*,**

    学习过程中遇到了*解包的过程,很感兴趣,于是实验一番, a = (1, 2, 3, 4, 5, 6) b = [2, 3, 4, 5, 5, 6] c = {"name": 'zh ...

  8. python list tuple 打包 解包_python的打包与解包

    python的*与**,在函数的定义与调用过程中,有着不同的作用 打包参数: 一.函数定义时,形参前加*号(如:*args):收集实参中所有的位置参数,打包成新元组并将该元组赋值给args变量 实参位 ...

  9. python中序列解包_Python3 序列解包

    转载自:https://blog.csdn.net/yilovexing/article/details/80576788 序列解包是 Python 3.0 之后才有的语法 什么是序列解包呢?先看一个 ...

最新文章

  1. HTML的标签描述10
  2. Redis持久化存储详解(一)
  3. 浅析网站建设基本流程
  4. 即使有历史最佳年报,安踏的未来依然有三重重担
  5. 经典的三栏布局:圣杯布局,双飞翼布局,flex布局
  6. 5-4日 socket套接字
  7. mysql pxc_MySQL之PXC集群搭建
  8. 续--Flask, Django - 区别
  9. java 如何判定消息已在队列_【05期】消息队列中,如何保证消息的顺序性?
  10. Math.toRadians
  11. 32个Python爬虫项目
  12. linux git 显示 分支,Linux 终端显示 Git 当前所在分支
  13. python求解括号匹配的相关问题
  14. hiBurn下载-hitool烧写鸿蒙2.0系统到Hi3861V100-从哪里找到芯片列表文件更新芯片列表-HarmonyOS
  15. 【学习】无刷直流电机的基本结构及工作原理
  16. Workface通用核算项目的实现
  17. 甲骨文服务器操作系统,甲骨文年内完成操作系统移换 Linux将成主要平台
  18. 用户态和内核态的切换耗费时间的原因
  19. webots车轮下陷问题 车轮在地下
  20. ShaderToy入门教程(2) - 光照和相机

热门文章

  1. 微信小程序多行文本超出显示省略号
  2. Linux下在shell中使用curl模拟get,post请求访问接口并设置代理
  3. js添加删除HTML元素
  4. netty框架学习及springboot整合集成
  5. java 新建文件_Java创建文件的常用方法
  6. java8系列02——Stream流
  7. git clone 本地仓库
  8. 图片预加载的三个方法
  9. 《RMPE: Regional Multi-Person Pose Estimation》论文阅读之AlphaPose
  10. CentOS之——CentOS 8 启动盘的安装