十一、python基础:函数各种参数的用法

1、为什么函数要有参数?

我们封装成一个函数的目的就是为了让它可以重复使用,如果想要让函数能适应更多的情况,我们就要给函数预留参数,可以让用户自己传入参数,处理不同条件下的需求。

2、函数的参数有哪些种类?

在python中,函数的参数可以分为以下几种:
位置参数、关键字参数、默认参数、多值参数

2.1、位置参数

def get_info(name, age, height):
    print(name)
    print(age, height)

这上面的get_info函数总共有三个参数:name, age, height。

它们是不是位置参数,取决于你调用的时候,是怎么给它传参的。

举例:
我们来看一下调用的时候,按照位置参数去传参是怎么样的

def get_info(name, age, height):
    print(name)
    print(age, height)
    
get_info('小明', 12, 180)    # 正确调用方式
get_info(12, '小明', 180)    # 错误调用方式,位置错了
get_info('小明', 12)     # 错误调用方式,参数缺少了

位置参数注意:
1、按照位置参数传参的时候,一定要注意位置不能放错了,否则函数获取到的数据就不对。
2、位置参数的数量是不能多也不能少的,定义函数时有3个位置参数,调用函数的时候,就必须传3个参数。
3、定义一个函数时,不管它有多少种类的参数,位置参数永远是放在其他类型参数前面的。

2.2、关键字参数

如果你不想按照位置的顺序给函数传参,也可以使用关键字参数传参。

def get_info(name, age, height):
    print(name)
    print(age, height)
    
get_info(age=12, name='小明', height=180)

按照这样键值对的方式传参,即使你的位置顺序放错了也不要紧,只要关键字写对了就行,看一下执行的结果:

def python 多个参数初始化 python函数多参数_默认值

2.3、默认参数(缺省参数)

默认参数也叫缺省参数,也就是你在传参时,可以不传这个参数,函数本身会给设置它一个默认值,你不传参就使用默认值。

一个参数是不是默认参数,不是取决于你调用时传参的方式,而是取决于定义时,有没有给这个参数设置默认值的。

我们把上面的函数稍微改一下,改成下面这样,给了height一个默认值180,在调用它的时候,我们可以传参,也可以不传,看看运行结果

def get_info(name, age, height=180):
    print(name)
    print(age, height)
    
get_info(age=12, name='小明')
get_info(age=12, name='xiaoming', height=170)

def python 多个参数初始化 python函数多参数_默认值_02


还是可以正常输出的,调用时如果有给默认参数传参,它就使用你传的参数,没有的话,就使用原本定义时设置的默认值。

注意:默认参数必须是在位置参数之后,我们来演示一下,给age一个默认值,放在中间,看看有什么效果。

def get_info(name, age=12, height):
    print(name)
    print(age, height)
    
get_info(12, 170)

结果会报错:

def python 多个参数初始化 python函数多参数_元组_03


def python 多个参数初始化 python函数多参数_元组_04

2.4、多值参数

有时候我们在定义函数的时候,允许用户传很多参数,但是参数的个数还不确定,这时候就可以使用多值参数了。

多值参数有2种表示方法,对应传不同类型的数据:

*args表示接收一个元组,元组的长度不作限制;
**kwargs表示接收一个字典,字典的长度不作限制;

def get_info(name, age, *args, **kwargs):
    print(name, age)
    print(*args)
    print(*kwargs)
    
t = (123, 345)
d = {'phone': '156XXX'}
get_info('小明', 12, t, d)

这里有个需要注意的地方:
我们在参数上是使用了"*args"和“**kwargs”,这是为了向解释器表达,我们要收集一个元组和一个字典。而在函数体中,我们使用的是“*args”和“*kwargs”,不管是args还是kwargs,前面都只有一个星号,这里不再表示收集的意思。而是向解释器表达,我们想要将收集到的元组和字典进行解包,就是你要一个一个元素给我拎出来,不要按照整体一个元组和一个字典输出。当然,如果你使用的是“args”和“kwargs”,它将会按照整体输出。

看看运行结果:

def python 多个参数初始化 python函数多参数_def python 多个参数初始化_05

这个结果看起来貌似没毛病对吧。
但是,其实它是有问题的!!!
看它的输出,我们明明在函数中设置了3次print(),打印出来的结果就应该是3行的,但为什么结果只输出了2行?可是打印出来的内容却没有缺少,全都输出了。

这里还有一点需要特别注意,上面造成这个问题的原因,是解释器把你传的2个参数t和d都收集到*args里面了,而**kwargs就没有收集到参数,因此,打印出来的只有2行。

解决方法:
在传参的时候,分别给2个参数加上符号*和**。

def get_info(name, age, *args, **kwargs):
    print(name, age)
    print(*args)
    print(*kwargs)
    
t = (123, 345)
d = {'phone': '1560000'}
get_info('小明', 12, *t, **d)

看一下输出结果:

def python 多个参数初始化 python函数多参数_元组_06


最后看一下函数体中不使用星号进行解包,会输出什么结果。

def python 多个参数初始化 python函数多参数_python_07

关于函数参数的建议:
注意最好不要使用可变类型数据容器,作为默认参数,也就是列表、字典这些,虽然你作为默认参数它不会报错,但是有时候会造成一些奇怪的问题。