Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。
位置参数
例如:
1 | def power(x): |
默认参数
1 | def power(x, n=2): |
可以在定义函数时,默认给上一个参数 n=2
使用默认参数能够最大的好处是能降低调用函数的难度。
默认参数很有用,但使用不当,也会掉坑里。默认参数有个最大的坑,演示如下:
1 | def add_end(L=[]): |
会输出
1 | [1, 2, 3, 'END'] |
我们可以看到,第一次和第二次输出都没有问题,因为我们传了参数进去,第三次我们输入,会返回默认的 ‘END’,但是第四次和第五次就有问题了。
原因解释如下:
Python函数在定义的时候,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,它指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
我们要修改下该函数
1 | def add_end(L=None): |
定义默认参数要牢记一点:默认参数必须指向不变对象!
为什么要设计str、None这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:
1 | def calc(num): |
但是调用的时候,需要先组装出一个list或tuple:
1 | print(calc([1,2,3])) |
改为可变参数.
1 | def calc(*num): |
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数
那如果要传入一个 list 或 tuple 呢
1 | def calc(*num): |
*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
关键字参数
1 | def person(name,age,**kw): |
和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符*,*后面的参数被视为命名关键字参数。
1 | def person(name,age,*,city='beijing',job): |
传入tuple 和 dict
args = (1,2,3,4,5)
kw = {'d':99,'x':44}
print(f1(*args,**kw))
*args是可变参数,args接收的是一个tuple;
**kw是关键字参数,kw接收的是一个dict。
学习笔记来自廖雪峰的 python