函数的参数:Python中函数定义非常简单,由于函数参数的存在,使函数变得非常灵活应用广泛;不但使得函数能够处理复杂多变的参数,还能简化函数的调用。
Python中的函数参数有如下几种:位置参数、默认参数、可变参数、关键字参数和命名关键字参数
一、位置参数
位置参数(positional arguments)就是其他语言的参数,其他语言没有分参数的种类是因为只有这一种参数, 所有参数都遵循按位置一一对应的原则 。
计算x^2 的函数:
1
2
3
|
def power(x): return x * x power( 2 ) |
对于power(x) 函数,参数x就是一个 位置参数
,也叫做 必选参数
。当我们调用power函数时,必须传入有且仅有的一个参数x。
现在,如果我们要计算 x^3 怎么办?可以再定义一个power3 函数,但是如果要计算 x^4 、 x^5 ……怎么办?我们不可能定义无限多个函数。
你也许想到了,可以把power(x) 修改为power(x, n) ,用来计算 x^n ,说干就干:
1
2
3
4
5
6
|
def power(x,n): s = 1 while n > 0 : s = s * x n = n - 1 return s |
对于这个修改后的power(x, n) 函数,可以计算任意n次方
1
2
|
print (power( 2 , 10 )) print (power( 1 , 10 )) |
输出:
1024
1
修改后的power(x, n) 函数有两个参数:x和n,这两个参数都是位置参数,调用函数时,传入的两个值 按照位置顺序 依次赋给参数x 和n 。
二、默认参数
由于我们经常计算 x^2 ,所以,完全可以把第二个参数n 的默认值设定为2,这个时候,默认参数就派上用场了。
1
2
3
4
5
6
7
8
9
|
def power(x,n = 2 ): s = 1 while n > 0 : s = s * x n = n - 1 return s print (power( 4 )) print (power( 3 ,n = 3 )) print (power( 2 , 4 )) |
输出:
16
27
16
这样,当我们调用power(4) 时,相当于调用power(4, 2) :而对于n > 2 的其他情况,就必须明确地传入n ,比如power(2, 4) 。
从上面的例子可以看出, 默认参数可以简化函数的调用 。
设置默认参数时,有几点要注意:
1、必选参数(位置参数)在前,默认参数在后,否则Python的解释器会报错
2、当函数有多个参数时,把变化大的参数放前面,变化小的参数放后面。变化小的参数就可以作为默认参数
使用默认参数有什么好处?
举个例子,我们写个一年级小学生注册的函数,需要传入name 、gender 、age、city四个参数:
由于大多数学生注册时年龄和城市基本一样,就可以把年龄和城市设置为默认参数,这样,大多数学生注册时不需要提供年龄和城市,只提供必须的两个参数,只有与默认参数不符的学生才需要提供额外的信息。
1
2
3
4
5
6
7
8
9
10
11
|
#学籍输入 def enroll(name,gender,age = 6 ,city = 'BJ' ): print ( 'name is: ' ,name) print ( 'gender is: ' ,gender) print ( 'age is: ' ,age) print ( 'city is: ' ,city, '\n' ) enroll( 'Tom' , 'M' ) enroll( 'Lisa' , 'f' ) enroll( 'Bob' , 'M' , 7 ) enroll( 'Lucy' , 'F' , 7 , 'TJ' ) enroll( 'Jerry' , 'M' ,city = 'SH' ) |
输出:
name is: Tom
gender is: M
age is: 6
city is: BJ
name is: Lisa
gender is: f
age is: 6
city is: BJ
name is: Bob
gender is: M
age is: 7
city is: BJ
name is: Lucy
gender is: F
age is: 7
city is: TJ
name is: Jerry
gender is: M
age is: 6
city is: SH
可见,默认参数降低了函数调用的难度,而一旦需要更复杂的调用时,又可以传递更多的参数来实现。无论是简单调用还是复杂调用,函数只需要定义一个。
注意:默认参数有个最大的坑,演示如下:
先定义一个函数,传入一个list,添加一个end 再返回:
1
2
3
|
def add_end( list = []): list .append( 'end' ) return list |
当你正常调用时,结果似乎不错:
1
2
|
print (add_end([ 1 , 2 , 3 ])) print (add_end([ 'x' , 'y' ])) |
输出:
[1, 2, 3, 'end']
['x', 'y', 'end']
1
2
3
4
5
|
#当你使用默认参数调用时,一开始结果也是对的: print (add_end()) #但是,再次调用add_end() 时,结果就不对了: print (add_end()) print (add_end()) |
输出:
['end']
['end', 'end']
['end', 'end', 'end']
很多初学者很疑惑,默认参数是[] ,但是函数似乎每次都“记住了”上次添加了'end' 后的list。原因解释如下:
Python函数在定义的时候,默认参数list的值就被计算出来了,即[] ,因为默认参数list也是一个变量,它指向对象[] ,每次调用该函数,如果改变了list的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了。
定义默认参数要牢记一点:默认参数必须指向不变对象!
因此定义默认参数时一定要使用不可变对象(int、float、str、tuple)。使用可变对象语法上没错,但在逻辑上是不安全的,代码量非常大时,容易产生很难查找的bug。
要修改上面的例子,我们可以用None 这个不变对象来实现:
1
2
3
4
5
6
7
8
9
10
|
def add_end( list = None ): if list = = None : list = [] list .append( 'end' ) return list print (add_end([ 1 , 2 , 3 ])) print (add_end([ 'x' , 'y' ])) print (add_end()) print (add_end()) print (add_end()) |
输出:
[1, 2, 3, 'end']
['x', 'y', 'end']
['end']
['end']
['end']
现在,无论调用多少次,都不会有问题。
为什么要设计str 、 None 这样的不变对象呢?因为不变对象一旦创建,对象内部的数据就不能修改,这样就减少了由于修改数据导致的错误。此外,由于对象不变,多任务环境下同时读取对象不需要加锁,同时读一点问题都没有。我们在编写程序时,如果可以设计一个不变对象,那就尽量设计成不变对象。
三、可变参数
在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。
我们以数学题为例子,给定一组数字a,b,c…… ,请计算a^2 + b^2 + c^2 +...
要定义出这个函数,我们必须确定输入的参数。由于参数个数不确定,我们首先想到可以把a,b,c……作为一个list或tuple传进来,这样,函数可以定义如下:
1
2
3
4
5
6
7
|
def calculator(numbers): sum = 0 for n in numbers: sum = sum + n * n return sum print (calculator([ 2 , 3 ])) print (calculator(( 3 , 5 , 6 ))) |
输出:
13
70
但是调用的时候,需要先组装出一个list 或tuple,如果利用可变参数,调用函数的方式就可以简化:
1
2
3
4
5
6
7
|
def calculator( * numbers): sum = 0 for n in numbers: sum = sum + n * n return sum print (calculator( 2 , 3 )) print (calculator( 3 , 5 , 6 )) |
输出:
13
70
定义可变参数和定义一个list 或tuple 参数相比,仅仅在参数前面加了一个* 号。在函数内部,参数numbers接收到的是一个tuple(可变参数将以tuple形式传递),因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数。
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:
1
2
|
nums = [ 2 , 3 , 4 ] print (calculator(nums[ 0 ],nums[ 1 ],nums[ 2 ])) |
输出:
29
这种写法当然是可行的,问题是太繁琐,所以Python允许你* 在list或tuple前面加一个 号**,把list或tuple的元素变成可变参数传进去:
1
2
|
nums = [ 2 , 3 , 4 ] print (calculator( * nums)) |
输出:
29
nums 表示把nums 这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。
四、关键字参数
python的可变参数以tuple形式传递,而关键字参数则是以dict形式传递。
即可变参数传递的是参数值,关键字参数传递的是参数名:参数值键值对。
形式: **kw
这是惯用写法,建议使用,容易被理解
1
2
3
4
|
def stu_info(name,gender, * * kw): print ( 'name is:' ,name, ' gender is:' ,gender, ' other is :' ,kw) stu_info( 'Bob' , 'M' ,age = 7 ,city = 'TJ' ) stu_info( 'Lucy' , 'F' ,city = 'BJ' ) |
输出:
name is: Bob gender is: M other is : {'age': 7, 'city': 'TJ'}
name is: Lucy gender is: F other is : {'city': 'BJ'}
可变参数和关键字参数都可以接受0个或者多个参数
五、命名关键字参数
Python的命名关键字参数对传入的关键字参数做了进一步的限制。
格式:在关键字参数前增加一个”*”。
1
2
3
4
|
def stu_info(name,gender, * ,age,city): print ( 'name is:' ,name, ' gender is:' ,gender, ' age:' ,age, ' city:' ,city) stu_info( 'Bob' , 'M' ,age = 7 ,city = 'TJ' ) stu_info( 'Lucy' , 'F' ,city = 'BJ' ,age = 10 ) |
输出:
name is: Bob gender is: M age: 7 city: TJ
name is: Lucy gender is: F age: 10 city: BJ
* 关键字参数和命名关键字参数的区别在于,前者可以传递任何名字的参数,而后者只能传递 后面名字的参数。* 如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符 了:
1
2
3
4
5
6
7
|
#args可以传递一个tuple 其后只能传递age和city参数 def stu_info(name,gender, * args,age,city): print ( 'name is:' ,name, ' gender is:' ,gender, ' age:' ,age, ' city:' ,city) for i in args: print ( 'args:' ,i) stu_info( 'Bob' , 'M' ,age = 7 ,city = 'TJ' ) stu_info( 'Lucy' , 'F' ,( 2 , 3 ),city = 'BJ' ,age = 10 ) |
输出:
name is: Bob gender is: M age: 7 city: TJ
name is: Lucy gender is: F age: 10 city: BJ
args: (2, 3)
六、各种参数之间的组合
一次函数调用可以传递以上所述任何一种参数或者多种参数的组合,当然也可以没有任何参数。正如默认参数必须在最右端一样,使用多种参数时也对顺序有严格要求,也是为了解释器可以正确识别到每一个参数。
顺序:位置参数、默认参数、可变参数、命名关键字参数和关键字参数。
1
2
|
def function(a, b, c = 0 , * , d, * * kw): print ( 'a =' , a, 'b =' , b, 'c =' , c, 'd =' , d, 'kw =' , kw) |
可读性是代码的一个很重要的要求,所以尽量避免使用多种参数的组合。
到此这篇关于Python中的多个函数参数的文章就介绍到这了,更多相关Python中的函数参数内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.51cto.com/u_5839280/3799375