目錄
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)參數組合在使用的時候是有順序的,依次是必選參數、預設參數、可變參數和關鍵字參數。