iT邦幫忙

2022 iThome 鐵人賽

DAY 27
0

今天我們來學習關鍵字引數。

回憶一下之前學到的:函式的位置參數可以用關鍵字引數的方式傳入:

def func1(a, b, c):
    print(a, b, c)
func1(10, 20, 30)
10 20 30
func1(b=20, c=30, a=10)
10 20 30
func1(10, c=30, b=20)
10 20 30

是否要用關鍵字引數是由呼叫函式的人自行決定,那我們有沒有方式強制函式呼叫時必須用關鍵字引數?

有的,我們可以 exhausting 位置引數,後面的參數就必須用關鍵字引數傳入:

def func1(a, b, *args, d):
    print(a, b, args, d)

上面的函式,在 *args 後面的位置引數都被 exhausted,於是只能用關鍵字引數傳入。

下面嘗試將 d 參數用位置引數呼叫就會出錯:

func1(10, 20, 'a', 'b', 100)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

/Users/maotingyang/Downloads/Keyword Arguments.ipynb Cell 12 in <cell line: 1>()
----> <a href='vscode-notebook-cell:/Users/maotingyang/Downloads/Keyword%20Arguments.ipynb#X15sZmlsZQ%3D%3D?line=0'>1</a> func1(10, 20, 'a', 'b', 100)


TypeError: func1() missing 1 required keyword-only argument: 'd'

這就對了:

func1(10, 20, 'a', 'b', d=100)
10 20 ('a', 'b') 100

我們甚至可以設計一個位置引數非必備、關鍵字引數必備的函式:

def func1(*args, d):
    print(args)
    print(d)
func1(1, 2, 3, d='hello')
(1, 2, 3)
hello

這個函式位置引數非必備,所以也可以這樣呼叫:

func1(d='hello')
()
hello

然而關鍵字引數必備(因為我們沒給 default value),所以不給就會出錯:

func1()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

/Users/maotingyang/Downloads/Keyword Arguments.ipynb Cell 21 in <cell line: 1>()
----> <a href='vscode-notebook-cell:/Users/maotingyang/Downloads/Keyword%20Arguments.ipynb#X31sZmlsZQ%3D%3D?line=0'>1</a> func1()


TypeError: func1() missing 1 required keyword-only argument: 'd'

如何讓關鍵字引數非必備?給一個 default value 就可以了:

def func1(*args, d='n/a'):
    print(args)
    print(d)
func1(1, 2, 3)
(1, 2, 3)
n/a
func1()
()
n/a

有時候我們想要禁止所有位置引數傳入,可以這樣寫:

def func1(*, d='hello'):
    print(d)
func1(10, d='bye')
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

/Users/maotingyang/Downloads/Keyword Arguments.ipynb Cell 28 in <cell line: 1>()
----> <a href='vscode-notebook-cell:/Users/maotingyang/Downloads/Keyword%20Arguments.ipynb#X41sZmlsZQ%3D%3D?line=0'>1</a> func1(10, d='bye')


TypeError: func1() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given
func1(d='bye')
bye

用一個單 * 號代表呼叫函式必須用關鍵字引數,以下就對了:

def func1(*, a, b):
    print(a)
    print(b)
func1(a=10, b=20)
10
20

用位置引數傳會出錯:

func1(10, 20)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

/Users/maotingyang/Downloads/Keyword Arguments.ipynb Cell 34 in <cell line: 1>()
----> <a href='vscode-notebook-cell:/Users/maotingyang/Downloads/Keyword%20Arguments.ipynb#X50sZmlsZQ%3D%3D?line=0'>1</a> func1(10, 20)


TypeError: func1() takes 0 positional arguments but 2 were given

之前我們學過,定義函式的位置參數時,只要某個參數給了預設值,後面的都要有預設值,關鍵字參數則沒有這個限制,給了預測值,後面的關鍵字參數可以無預設值:

def func1(a, *, b='hello', c):
    print(a, b, c)
func1(5, c='bye')
5 hello bye

下面是一個集大成的函式:位置參數、有預設值的位置參數、*args 參數(接下來位置引數被 exhausted)、關鍵字引數、有預設值的關鍵字引數:

def func1(a, b=20, *args, d=0, e='n/a'):
    print(a, b, args, d, e)
func1(5, 4, 3, 2, 1, d=0, e='all engines running')
5 4 (3, 2, 1) 0 all engines running
func1(0, 600, d='goooood morning', e='python!')
0 600 () goooood morning python!
func1(11, 'm/s', 24, 'mph', d='unladen', e='swallow')
11 m/s (24, 'mph') unladen swallow

如你所見,在 Python 中定義參數和傳入引數十分彈性。

明天我們再繼續研究 function parameters!


上一篇
*args
下一篇
**kwargs
系列文
小青蛇變大蟒蛇——進階Python學起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言