一、python参数问题:
1)位置参数(必需参数):调用函数时根据函数定义的参数位置来传递参数,调用时的数量必须和声明时的一样:
eg:
def fun(name,sex):
pass
fun(name1,sex1) #两个参数的顺序必须是一一对应的,自然参数个数也是要一样的了,
2)关键字参数:用于函数调用,通过‘键-值’形式加以指定,通俗的讲,就是指定你要传进来的参数值。很明显,这里说的不是我们常说的那种true、false关键字。除此之外,此可以让函数更加清晰,同时也清除了参数的顺序需求,也就是对参数顺序没有要求。
eg:
fun(name='yangrongkuan',sex=1) or
fun(name1,sex=2)
但是不能这样:fun(name='yangrongkuan',sex1)
因为,有位置参数时,位置参数必须要在关键字参数的前面,但关键字参数之间不存在先后顺序的。
3)默认参数:用于定义函数,为参数提供默认值,默认参数的赋值只会在函数定义的时候绑定一次,默认值不会再被修改。调用函数时可传可不传该默认参数的值。(所有位置参数必须出现在默认参数前,包括函数定义和调用)
4)可变参数:定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时,可用包裹(packing)位置参数/关键字参数,来进行参数传递。
1、包裹位置传递:我们传进去的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(args是元组类型)。
eg:
def fun(*args):
pass
fun()
fun(a)
fun(a,b,c)
2、包裹关键字传递:kargs是字典类型,收集所有的关键字参数。
eg:
def fun(**kargs):
pass
fun(a=1)
fun(a=1,b=1,c=2)
备注:
1、*args和**kargs都是python的可变参数,前者表示任何多个无名参数,是元组类型,后者表示关键字参数,是字典类型。若同时使用两个参数的话,必须*args参数列要在**kargs前。
2、*args重点在*,后面的args相当于一个变量名,可以自己定义的,它的本质是将标准调用剩下的值集中转变为元组。**kargs也一样,它的本质就是将关键字调用剩下的值集中转变为字典。
3、位置参数,默认参数,可变参数的混合使用:位置参数->*args->默认参数(如果默认参数在调用的过程中是需要进行修改的,那么要调整默认参数的位置到args之前,但不能放在开头,这也说明了,如果没有位置参数的话,默认参数也不用在调用过程中进行修改。【这里默认参数的修改类似于函数调用时引用传递,并不是真正改变原函数设定的那个默认参数的值】)->**kargs
5)解包裹参数:*和**也可以在函数调用的时候使用,称之为解包裹(unpacking)
1、在传递元组时,让元组的每一个元素对应一个位置参数:
eg:
def fun(name, password):
pass
args = ('yangrongkuan', '123456')
fun(*args)
输出:yangrongkuan 123456
2、在传递字典时,让字典的每个键值对作为一个关键字参数传递给函数:
eg:
def fun(kargs):
pass
kargs = {'name':'yangrongkuan','password':'123456'}
fun(**args)
输出:{'name':'yangrongkuan','password':'123456'}
6)强制位置参数:Python3.8 新增了一个函数形参语法'/'用来指明函数形参必须使用指定位置参数,不能使用关键字参数的形式。
eg:
def fun(a, b, /, c, d):
pass
fun(10, 20, 30, d=40)#调用正确
fun(10, b=20, c=30, d=40)#调用错误:b不能使用关键字参数的形式
在上例中,形参a,b必须使用指定位置参数,c或d可以是位置参数/关键字参数。
二、参数传递问题:python 中一切都是对象,严格意义我们不能说值传递还是引用传递,我们应该说传的是不可变对象还是可变对象。
1)在python中,类型属于对象,变量是没有类型的。比如:a=10,10是整型;a=[1,2,3],其中[1,2,3]是List类型,而变量a是没有类型的,它只是一个对象的引用,可以指向任意类型对象的引用。
2)在弄清python参数传递问题之前要先来了解一下python中的可更改(mutable)对象和不可更改(immutable)对象:
1、可更改对象(可变类型):List,Dictionary,Set:如fun(a),则是将a真正的传过去,修改后fun外部的a也会受影响:举个例子:
eg:可更改类型是这样子理解:变量赋值a=[1,2,3,4]后再赋值a[2]=5则是将列表a的第三个元素值更改,本身a没有动,只是其内部的一部分值被修改了。
2、不可更改对象(不可变类型):Number,String,Tuple:如fun(a)传递的只是a的值,没有影响到a值的本身:举个例子:
eg:不可更改的类型是这样子理解:变量赋值a=5后再赋值a=10,这里实际是新生成一个int值对象10,再让a指向它而5被丢弃,不是改变a的值,相当于新生成了a。