对于python函数参数,对于初学者可能就是进入了迷宫,尽管我也是初学者,简单总结一下。
我们注重客户提出的每个要求,我们充分考虑每一个细节,我们积极的做好成都网站建设、网站设计服务,我们努力开拓更好的视野,通过不懈的努力,成都创新互联赢得了业内的良好声誉,这一切,也不断的激励着我们更好的服务客户。 主要业务:网站建设,网站制作,网站设计,小程序设计,网站开发,技术开发实力,DIV+CSS,PHP及ASP,ASP.Net,SQL数据库的技术开发工程师。
说参数之前,先讲一下两个packing(包裹)和unpacking(解包裹):
输出:
我总结不了这个概念,只能帮大家到这了
一、位置参数和关键字参数:
调用函数时根据函数定义的参数位置来传递参数。
注意:
有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的
二、默认参数:
用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
三、可变参数:
定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递,会显得非常方便。
1、包裹位置传递
我们传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包位置传递。
2、包裹关键字传递
kargs是一个字典(dict),收集所有关键字参数
四、解包裹参数:
*args 和 **kargs ,也可以在函数调用的时候使用,称之为解包(unpacking)
1、在传递元组时,让元组的每一个元素对应一个位置参数
2、在传递词典字典时,让词典的每个键值对作为一个关键字参数传递给函数
五、位置参数、默认参数、可变参数的混合使用
1、基本原则是:先位置参数,默认参数,包裹位置,包裹关键字(定义和调用都应遵循)
2、Python中 *args 和 **kwargs 的区别
先看个demo:
输出结果:
分析一下:可以看到,这两个是[Python]中的可变参数。 *args 表示任何多个无名参数,它是一个tuple; **kwargs 表示关键字参数,它是一个dict。并且同时使用 *args 和 **kwargs 时,必须 *args 参数列要在 **kwargs 前,否则会报语法错误!!!
还有个小应用场景:创建字典
其实python中就带有dict类,使用dict(a=1,b=2,c=3)即可创建一个字典了。
*args:
重点在*,后面的args相当于一个变量名,可以自己定义的。它的本质就是将标准调用剩下的值集中转变为元组。
从形参的角度:
从实参的角度:
从不同角度看**kwargs:
**kwargs与位置参数和默认参数混用:
超复杂混合参数混用记:
总结:
位置参数:
调用函数时所传参数的位置必须与定义函数时参数的位置相同
关键字参数:
使用关键字参数会指定参数值赋给哪个形参,调用时所传参数的位置可以任意
*位置参数:可接受任意数量的位置参数(元组);只能作为最后一个位置参数出现,其后参数均为关键字参数
**关键字参数:可接受任意数量的关键字参数(字典);只能作为最后一个参数出现
上一期我们学习参数传递怎么传递,也了解了参数的几种类型。
首先,我们再来回顾一下,形参和实参:
形参是在定义函数时定义的,放在函数名后面的圆括号里,可为空
实参是调用函数时为形参传入具体的参数值
简单总结一下,谁调用函数,谁就负责传入参数。
好呐,本期我们来详细学习函数几种参数类型,大纲如下:
python函数的参数名是无意义的,Python允许在调用函数时通过通过名字来传入参数值。
位置参数:按照形参位置传入的参数
调用函数时,实参默认按位置顺序传递的。同时实参个数也要和形参匹配
举一个小栗子
如果实参的个数与形参不匹配时,调用函数运行就会报错
Python中,形参与调用函数紧密联系在一起的。
关键字参数:调用函数时,使形参名称来传递参数,形式为“形参名=实参”
关键字参数,又叫命名参数,传递时无需考虑参数位置和顺序
举一个小栗子
默认参数:定义函数时,我们可以为形参提前设置具体的值。
在定义函数时,默认参数要放到位置等其他参数后面
在调用函数时,默认参数是可选的。如果传入新值,则会覆盖默认值
举一个小栗子
注意,默认值不能位于位置参数前面,否则程序会报错误
不定长参数又名可变参数。
不定长参数指的是可变数量的参数,分两种情况:
如果不定长参数后面,可以新增参数吗?
我们通过例子来看,会发生什么?
运行上面的程序,Python解释器会报错
原因是,形参a已经是不定长参数,我们调用的test(2,3,4)传入的三个实参,系统自动把它们属于形参a的值,形参b 和形参c就等于没有值传入,这时候系统就认为,调用函数的对象,参数没有传够。
为了解决这一报错,python引入了 强制命名参数
规定,调用不定参数后面有跟位置参数的函数时,传入给位置参数时,必须要强制命名参进行传参。
逆向参数收集针对的对象传入函数的实参
调用函数时,如果实参是元组,列表或者字典,通过在实参前面加入星号,可以自动把元素进行隔开,然后再转入给函数进行处理
举一个小栗子
本期,我们详细学习了参数几种类型,为后面我们学习函数,打好基础。
实践是检验真理的过程,大家多动手练习练习,会有不一样的奇妙旅程~
好呐,以上是本期内容,欢迎大佬们评论区指正~
python 的函数参数类型分为4种:
1.位置参数:调用函数时根据函数定义的参数位置来传递参数,位置参数也可以叫做必要参数,函数调用时必须要传的参数。
当参数满足函数必要参数传参的条件,函数能够正常执行:
add(1,2) #两个参数的顺序必须一一对应,且少一个参数都不可以
当我们运行上面的程序,输出:
当函数需要两个必要参数,但是调用函数只给了一个参数时,程序会抛出异常
add(1)
当我们运行上面的程序,输出:
当函数需要两个必要参数,但是调用函数只给了三个参数时,程序会抛出异常
add(1,2,3)
当我们运行上面的程序,输出
2.关键字参数:用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
add(1,2) # 这种方式传参,必须按顺序传参:x对应1,y对应:2
add(y=2,x=1) #以关健字方式传入参数(可以不按顺序)
正确的调用方式
add(x=1, y=2)
add(y=2, x=1)
add(1, y=2)
以上调用方式都是允许的,能够正常执行
错误的调用方式
add(x=1, 2)
add(y=2, 1)
以上调用都会抛出SyntaxError 异常
上面例子可以看出:有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的
3.默认参数:用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值,所有位置参数必须出现在默认参数前,包括函数定义和调用,有多个默认参数时,调用的时候,既可以按顺序提供默认参数,也可以不按顺序提供部分默认参数。当不按顺序提供部分默认参数时,需要把参数名写上
默认参数的函数定义
上面示例第一个是正确的定义位置参数的方式,第二个是错误的,因为位置参数在前,默认参数在后
def add1(x=1,y) 的定义会抛出如下异常
默认参数的函数调用
注意:定义默认参数默认参数最好不要定义为可变对象,容易掉坑
不可变对象:该对象所指向的内存中的值不能被改变,int,string,float,tuple
可变对象,该对象所指向的内存中的值可以被改变,dict,list
这里只要理解一下这个概念就行或者自行百度,后续会写相关的专题文章讲解
举一个简单示例
4.可变参数区别:定义函数时,有时候我们不确定调用的时候会多少个参数,j就可以使用可变参数
可变参数主要有两类:
*args: (positional argument) 允许任意数量的可选位置参数(参数),将被分配给一个元组, 参数名前带*,args只是约定俗成的变量名,可以替换其他名称
**kwargs:(keyword argument) 允许任意数量的可选关键字参数,,将被分配给一个字典,参数名前带**,kwargs只是约定俗成的变量名,可以替换其他名称
*args 的用法
args 是用来传递一个非键值对的可变数量的参数列表给函数
语法是使用 符号的数量可变的参数; 按照惯例,通常是使用arg这个单词,args相当于一个变量名,可以自己定义的
在上面的程序中,我们使用* args作为一个可变长度参数列表传递给add()函数。 在函数中,我们有一个循环实现传递的参数计算和输出结果。
还可以直接传递列表或者数组的方式传递参数,以数组或者列表方式传递参数名前面加(*) 号
理解* * kwargs
**kwargs 允许你将不定长度的键值对, 作为参数传递给函数,这些关键字参数在函数内部自动组装为一个dict
下篇详细讲解 *args, **kwargs 的参数传递和使用敬请关注
parameter 是函数定义的参数形式
argument 是函数调用时传入的参数实体。
对于函数调用的传参模式,一般有两种:
此外,
也是关键字传参
python的函数参数定义一般来说有五种: 位置和关键字参数混合 , 仅位置参数 , 仅关键字参数 , 可变位置参数 , 可变关键字参数 。其中仅位置参数的方式仅仅是一个概念,python语法中暂时没有这样的设计。
通常我们见到的函数是位置和关键字混合的方式。
既可以用关键字又可以用位置调用
或
这种方式的定义只能使用关键字传参的模式
f(*some_list) 与 f(arg1, arg2, ...) (其中some_list = [arg1, arg2, ...])是等价的
网络模块request的request方法的设计
多数的可选参数被设计成可变关键字参数
有多种方法能够为函数定义输出:
非常晦涩
如果使用可变对象作为函数的默认参数,会导致默认参数在所有的函数调用中被共享。
例子1:
addItem方法的data设计了一个默认参数,使用不当会造成默认参数被共享。
python里面,函数的默认参数被存在__default__属性中,这是一个元组类型
例子2:
在例子1中,默认参数是一个列表,它是mutable的数据类型,当它写进 __defauts__属性中时,函数addItem的操作并不会改变它的id,相当于 __defauts__只是保存了data的引用,对于它的内存数据并不关心,每次调用addItem,都可以修改 addItem.__defauts__中的数据,它是一个共享数据。
如果默认参数是一个imutable类型,情况将会不一样,你无法改变默认参数第一次存入的值。
例子1中,连续调用addItem('world') 的结果会是
而不是期望的
4.7.1. 默认参数值
最常用的一种形式是为一个或多个参数指定默认值。这会创建一个可以使用比定义是允许的参数更少的参数调用的函数,例如:
def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries 0:
raise OSError('uncooperative user')
print(complaint)
这个函数可以通过几种不同的方式调用:
只给出必要的参数:
ask_ok('Do you really want to quit?')
给出一个可选的参数:
ask_ok('OK to overwrite the file?', 2)
或者给出所有的参数:
ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
这个例子还介绍了 in 关键字。它测定序列中是否包含某个确定的值。
默认值在函数 定义 作用域被解析,如下所示:
i = 5
def f(arg=i):
print(arg)
i = 6
f()
将会输出 5。
重要警告: 默认值只被赋值一次。这使得当默认值是可变对象时会有所不同,比如列表、字典或者大多数类的实例。例如,下面的函数在后续调用过程中会累积(前面)传给它的参数:
def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
这将输出:
[1]
[1, 2]
[1, 2, 3]
如果你不想让默认值在后续调用中累积,你可以像下面一样定义函数:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
创建一个函数用来计算三个数的和,如下:
下来,我们对其进行调用:
假设我们要计算这个函数返回结果的平均值。那么此时,我们只需将和值除以参数个数即可,那么参数个数怎么获取呢?你可能会说:数一下就知道了。那么假设此时有很多的参数,你还去数吗?此时,明显这个方法是不恰当的,那么有没有更加方便、高效的方法呢?我们接着往下看。
通过上面这个例子,我们不但可以获取参数个数,还可以获取所有变量名以及默认返回值。此时,我们只需根据自己的需求,去应用就可以了,那么以上的问题,就自然解决了。