本文仅供个人记录和复习,不用于其他用途
默认参数
比如我们现在定义一个函数,用于计算x²:
|
|
那么如果我现在想计算x的次方,是不是又得重新写一遍呢?为了函数的泛用性,我们可以为它添加一个参数y
,用于表示函数的指数:
|
|
由于我们经常要计算x的平方,所以我们可以给n设定一个默认值:
|
|
如果不设定默认值,那么我们每次都得传入x的指数。而这个默认值能够让我们不传入指数,让Python默认执行x的平方运算。
注意一下,必选参数在前,默认参数在后,这个顺序是不能够改变的。想一想,如果默认参数可以在必选参数前,那么我们如何修改默认参数呢?如果我们每次都要提供默认参数,那么它显然就失去了默认的意义。
如果我们在调用函数时,需要修改默认参数的值,那么可以按照顺序提供参数。不过有的时候你想修改第二个默认参数,那么怎么办呢?
|
|
上面是一个拥有两个默认参数的函数,如果你只想改变province
的值,那么可以调用dataIn(‘miao’, 18, province = ‘tianjing’)
。
默认参数的陷阱
比如我们定义一个函数,用于给list添加一个结束符‘End’
:
|
|
你会发现效果还可以:
[1, 2, 3, 'End']
['x', 'y', 'z', 'End']
那么我们这么做呢:
|
|
结果看起来是对的:
['End']
但是当我们添加多个时:
|
|
就会得到下面的结果:
['End']
['End', 'End']
['End', 'End', 'End']
为什么会这样呢?我们设置的默认参数是[]
,而且应该是一个临时变量,函数结束时自动删除,怎么会记录之前的数据呢?
事实上,Python的函数有些不同,默认参数在函数定义时就已经创建。如果默认参数是一个可变对象,而且函数中也改变了它的值。那么Python就会保留这个可变对象,并且作为下次调用该函数时的默认值。
由于这个不同的之处,我们每添加一次‘End’
,默认参数[]
都会将它记录下来。因此,默认参数必须指向不变对象。
|
|
C++就不会产生这种情况,默认参数不会记录之前的值。那么怎么解决这个问题呢?
|
|
由于默认参数是None
,是一个不可变对象。因此Python不会保留它的值,哪怕它在函数体中被修改过。所以,我们能使用不可变对象时,最好不要使用类似于list的可变对象。
可变参数
我们还可以定义可变参数,也就是传入参数的个数可变。比如我们要计算a² + b² + c² + …,那么这个时候参数不确定,我们只能够将a、b、c…作为一个tuple或list传入:
|
|
那么调用这个函数时,就必须用list或tuple包装:
|
|
这样调用函数显得有些麻烦,我们可以将参数变为可变参数:
|
|
我们只需要添加一个*
,就可以传入任意个参数,包括0个参数:
|
|
但是呢,假如我还是要传入一个list或者tuple,那么怎么办呢?如果直接传入是不行的,因为可变参数不能被list初始化。你当然可以这么做:
|
|
不过这样太麻烦了,我们可以在num前面加上一个*
,这样就可以把list中的元素转变为可变参数传入:
|
|
关键字参数
可变参数可以接受任意个数的参数,并且把它们包装成tuple,给函数块调用。而关键字参数则是接受任意个含参数名的参数,并且包装成一个dict:
|
|
name
和age
是必选参数,而kw
是关键字参数。我们可以只调用必选参数:
|
|
同时也可以传入任意个数的关键字参数:
|
|
输出如下:
name: miao age: 18 other: {'city': 'shanghai', 'job': 'student'}
关键字参数可用于扩展函数功能,比如用户注册时,有可选项和必选项,那么这就可以用到关键字参数。当然,你也可以直接将dict传入,不过这样很复杂,没有关键字参数方便。
多种参数组合
比如定义一个函数,包含以上四种参数形式:
|
|
事实上,这个函数用起来不是很方便。如果你要输入可变参数或者关键字参数,那么你就必须要提供默认参数。比如:
|
|
你以为是正确的?其实是错的。因为c
其实是默认参数,所以你不能够设置c
为关键字:
|
|
结果输出如下:
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'d': 99}
总之,我们在使用参数列表时,一定要注意参数的顺序。