目录
1 概述
2 定义函数
2.1 定义函数
2.2 没有参数和返回值的函数
2.3 返回多个值的函数
3 函数参数
3.1 必选参数
3.2 默认参数
3.3 可变参数
3.4 关键字参数
3.5 参数组合
4 小结
1 概述
在前面,我们已经对Python学习做了系统的知识梳理( Python思维导图)。Python基本数
据类型也分享完啦,本次分享函数。
2 定义函数
2.1 定义函数
在
Python
中,定义函数使用
def
语句。一个函数主要由三部分构成:
(1)函数名
(2)函数参数
(3)函数返回值
让我们看一个简单的例子:
1.
def
hello
(
name
):
2.
return
name
3.
4.
>>>
r
=
hello
(
'ethan'
)
5.
>>>
r
6.
'ethan'
在上面,我们定义了一个函数。函数名是
hello
;函数有一个参数,参数名是
name
;函数有一个 返回值,name
。
2.2 没有参数和返回值的函数
我们也可以定义一个没有参数和返回值的函数:
1.
def
greet
():
#
没有参数
2.
'hello world'
#
没有
return
,会自动
return None
3.
4.
>>>
r
=
greet
()
5.
hello world
6.
>>>
r
==
None
这里,函数
greet
没有参数,它也没有返回值(或者说是
None
)。
2.3 返回多个值的函数
我们还可以定义返回多个值的函数:
1.
>>>
def
add_one
(
x
,
y
,
z
):
2.
...
return
x
+
1
,
y
+
1
,
z
+
1
#
有
3
个返回值
3.
...
4.
>>>
5.
>>>
result
=
add_one
(
1
,
5
,
9
)
6.
>>>
result
# result
实际上是一个
tuple
7.
(
2
,
6
,
10
)
8.
>>>
type
(
result
)
9.
<
type
'tuple'
>
3 函数参数
在
Python
中,定义函数和调用函数都很简单,但如何定义函数参数和传递函数参数,则涉及到一些套路了。总的来说,Python
的函数参数主要分为以下几种:
(1)必选参数
(2)默认参数
(3)可变参数
(4)关键字参数
3.1 必选参数
必选参数可以说是最常见的了,顾名思义,必选参数就是在调用函数的时候要
传入数量一致
的参数,比 如:
1.
>>>
def
add
(
x
,
y
):
# x, y
是必选参数
2.
...
x
+
y
3.
...
4.
>>>
add
()
#
啥都没传,不行
5.
Traceback
(
most recent call last
):
6.
File
"<stdin>"
,
line
1
,
in
<
module
>
7.
TypeError
:
add
()
takes exactly
2
arguments
(
given
)
8.
>>>
add
(
1
)
#
只传了一个,也不行
9.
Traceback
(
most recent call last
):
10.
File
"<stdin>"
,
line
1
,
in
<
module
>
11.
TypeError
:
add
()
takes exactly
2
arguments
(
1
given
)
12.
>>>
add
(
1
,
2
)
#
数量一致,通过
13.
3
3.2 默认参数
默认参数是指在定义函数的时候提供一些默认值,如果在调用函数的时候没有传递该参数,则自动使用默认值,否则使用传递时该参数的值。
看看例子就明白了:
1.
>>>
def
add
(
x
,
y
,
z
=
1
):
# x, y
是必选参数,
z
是默认参数,默认值是
1
2.
...
x
+
y
+
z
3.
...
4.
>>>
add
(
1
,
2
,
3
)
# 1+2+3
5.
6
6.
>>>
add
(
1
,
2
)
#
没有传递
z
,自动使用
z=1
,即
1+2+1
7.
4
可以看到,默认参数使用起来也很简单,但有两点需要注意的是:
(1)默认参数要放在所有必选参数的后面
(2)默认参数应该使用不可变对象
比如,下面对默认参数的使用是错误的:
1.
>>>
def
add
(
x
=
1
,
y
,
z
):
# x
是默认参数,必须放在所有必选参数的后面
2.
...
return
x
+
y
+
z
3.
...
4.
File
"<stdin>"
,
line
1
5.
SyntaxError
:
non
-
default argument follows default argument
6.
>>>
7.
>>>
def
add
(
x
,
y
=
1
,
z
):
# y
是默认参数,必须放在所有必选参数的后面
8.
...
return
x
+
y
+
z
9.
...
10.
File
"<stdin>"
,
line
1
11.
SyntaxError
:
non
-
default argument follows default argument
再来看看为什么默认参数应该使用不可变对象。
我们看一个例子:
1.
>>>
def
add_to_list
(
L
=[]):
2.
...
L
.
append
(
'END'
)
3.
...
return
L
在上面的函数中,L 是一个默认参数,默认值是 [] ,表示空列表。
我们来看看使用:
1.
>>>
add_to_list
([
1
,
2
,
3
])
#
没啥问题
2.
[
1
,
2
,
3
,
'END'
]
3.
>>>
add_to_list
([
'a'
,
'b'
,
'c'
])
#
没啥问题
4.
[
'a'
,
'b'
,
'c'
,
'END'
]
5.
>>>
add_to_list
()
#
没有传递参数,使用默认值,也没啥问题
6.
[
'END'
]
7.
>>>
add_to_list
()
#
没有传递参数,使用默认值,竟出现两个
'END'
8.
[
'END'
,
'END'
]
9.
>>>
add_to_list
()
#
糟糕了,三个
'END'
10.
[
'END'
,
'END'
,
'END'
]
为啥呢?我们在调用函数的时候没有传递参数,那么就默认使用
L=[]
,经过处理,
L
应该只有一 个元素,怎么会出现调用函数两次,L
就有两个元素呢? 原来,L
指向了可变对象
[]
,当你调用函数时,
L
的内容发生了改变,默认参数的内容也会跟着变,也就是,当你第一次调用时,L
的初始值是
[]
,当你第二次调用时,
L
的初始值是
['END']
,等等。
所以,为了避免不必要的错误,我们应该使用不可变对象作为函数的默认参数。
3.3 可变参数
在某些情况下,我们在定义函数的时候,无法预估函数应该制定多少个参数,这时我们就可以使用可变参数了,也就是,
函数的参数个数是不确定的
。
看看例子:
1.
>>>
def
add
(*
numbers
):
2.
...
sum
=
3.
...
for
i
in
numbers
:
4.
...
sum
+=
i
5.
...
'numbers:'
,
numbers
6.
...
return
sum
在上面的代码中,
numbers
就是一个可变参数,参数前面有一个
*
号,表示是可变的。在函数内部,参数 numbers
接收到的是一个 tuple
。
在调用函数时,我们可以给该函数传递任意个参数,包括
个参数:
1.
>>>
add
()
#
传递
个参数
2.
numbers
: ()
3.
4.
>>>
add
(
1
)
#
传递
1
个参数
5.
numbers
: (
1
,)
6.
1
7.
>>>
add
(
1
,
2
)
#
传递
2
个参数
8.
numbers
: (
1
,
2
)
9.
3
10.
>>>
add
(
1
,
2
,
3
)
#
传递
3
个参数
11.
numbers
: (
1
,
2
,
3
)
12.
6
上面的
*
表示任意参数,实际上,它还有另外一个用法:用来给函数传递参数。
看看例子:
1.
>>>
def
add
(
x
,
y
,
z
):
#
有
3
个必选参数
2.
...
return
x
+
y
+
z
3.
...
4.
>>>
a
= [
1
,
2
,
3
]
5.
>>>
add
(
a
[
],
a
[
1
],
a
[
2
])
#
这样传递参数很累赘
6.
6
7.
>>>
add
(*
a
)
#
使用
*a
,相当于上面的做法
8.
6
9.
>>>
b
= (
4
,
5
,
6
)
10.
>>>
add
(*
b
)
#
对元组一样适用
11.
15
再看一个例子:
1.
>>>
def
add
(*
numbers
):
#
函数参数是可变参数
2.
...
sum
=
3.
...
for
i
in
numbers
:
4.
...
sum
+=
i
5.
...
return
sum
6.
...
7.
>>>
a
= [
1
,
2
]
8.
>>>
add
(*
a
)
#
使用
*a
给函数传递参数
9.
3
10.
>>>
a
= [
1
,
2
,
3
,
4
]
11.
>>>
add
(*
a
)
12.
10
3.4 关键字参数
可变参数允许你将不定数量的参数传递给函数,而关键字参数则允许你将
不定长度的键值对
,
作为参数传递给一个函数。
让我们看看例子:
1.
>>>
def
add
(**
kwargs
):
2.
return
kwargs
3.
>>>
add
()
#
没有参数,
kwargs
为空字典
4.
{}
5.
>>>
add
(
x
=
1
)
# x=1 => kwargs={'x': 1}
6.
{
'x'
:
1
}
7.
>>>
add
(
x
=
1
,
y
=
2
)
# x=1, y=2 => kwargs={'y': 2, 'x': 1}
8.
{
'y'
:
2
,
'x'
:
1
}
在上面的代码中,
kwargs
就是一个关键字参数,它前面有两个
*
号。
kwargs
可以接收不定长度的键值对,在函数内部,它会表示成一个 dict
。
和可变参数类似,我们也可以使用 **kwargs 的形式来调用函数,比如:
1.
>>>
def
add
(
x
,
y
,
z
):
2.
...
return
x
+
y
+
z
3.
...
4.
>>>
dict1
= {
'z'
:
3
,
'x'
:
1
,
'y'
:
6
}
5.
>>>
add
(
dict1
[
'x'
],
dict1
[
'y'
],
dict1
[
'z'
])
#
这样传参很累赘
6.
10
7.
>>>
add
(**
dict1
)
#
使用
**dict1
来传参,等价于上面的做法
8.
10
再看一个例子:
1.
>>>
def
sum
(**
kwargs
):
#
函数参数是关键字参数
2.
...
sum
=
3.
...
for
k
,
v
in
kwargs
.
items
():
4.
...
sum
+=
v
5.
...
return
sum
6.
>>>
sum
()
#
没有参数
7.
8.
>>>
dict1
= {
'x'
:
1
}
9.
>>>
sum
(**
dict1
)
#
相当于
sum(x=1)
10.
1
11.
>>>
dict2
= {
'x'
:
2
,
'y'
:
6
}
12.
>>>
sum
(**
dict2
)
#
相当于
sum(x=2, y=6)
13.
8
3.5 参数组合
在实际的使用中,我们经常会同时用到必选参数、默认参数、可变参数和关键字参数或其中的某些。但是,需要注意的是,它们在使用的时候是有顺序的,依次是必选参数、默认参数、可变参数和关键字参数。
比如,定义一个包含上述四种参数的函数:
1.
>>>
def
func
(
x
,
y
,
z
=
, *
args
, **
kwargs
):
2.
'x ='
,
x
3.
'y ='
,
y
4.
'z ='
,
z
5.
'args ='
,
args
6.
'kwargs ='
,
kwargs
在调用函数的时候,
Python
会自动按照参数位置和参数名把对应的参数传进去。
让我们看看:
1.
>>>
func
(
1
,
2
)
#
至少提供两个参数,因为
x, y
是必选参数
2.
x
=
1
3.
y
=
2
4.
z
=
5.
args
= ()
6.
kwargs
= {}
7.
>>>
func
(
1
,
2
,
3
)
# x=1, y=2, z=3
8.
x
=
1
9.
y
=
2
10.
z
=
3
11.
args
= ()
12.
kwargs
= {}
13.
>>>
func
(
1
,
2
,
3
,
4
,
5
,
6
)
# x=1, y=2, z=3, args=(4, 5, 6), kwargs={}
14.
x
=
1
15.
y
=
2
16.
z
=
3
17.
args
= (
4
,
5
,
6
)
18.
kwargs
= {}
19.
>>>
func
(
1
,
2
,
4
,
u
=
6
,
v
=
7
)
# args = (), kwargs = {'u': 6, 'v': 7}
20.
x
=
1
21.
y
=
2
22.
z
=
4
23.
args
= ()
24.
kwargs
= {
'u'
:
6
,
'v'
:
7
}
25.
>>>
func
(
1
,
2
,
3
,
4
,
5
,
u
=
6
,
v
=
7
)
# args = (4, 5), kwargs = {'u': 6, 'v': 7}
26.
x
=
1
27.
y
=
2
28.
z
=
3
29.
args
= (
4
,
5
)
30.
kwargs
= {
'u'
:
6
,
'v'
:
7
}
我们还可以通过下面的形式来传递参数:
1.
>>>
a
= (
1
,
2
,
3
)
2.
>>>
b
= {
'u'
:
6
,
'v'
:
7
}
3.
>>>
func
(*
a
, **
b
)
4.
x
=
1
5.
y
=
2
6.
z
=
3
7.
args
= ()
8.
kwargs
= {
'u'
:
6
,
'v'
:
7
}
4 小结
(1)默认参数要放在所有必选参数的后面。
(2)应该使用不可变对象作为函数的默认参数。
(3)*args
表示可变参数,
**kwargs
表示关键字参数。
(4)参数组合在使用的时候是有顺序的,依次是必选参数、默认参数、可变参数和关键字参数。