2012-09-08 35 views
8

我正在學習使用python的位置參數,也想看看他們在與默認參數混合起來是如何工作的: -位置參數之前使用默認參數

def withPositionalArgs(ae=9,*args): 
    print 'ae= ', ae 
    print 'args = ', args 


a=1 
b=2 
c=[10,20] 

withPositionalArgs(a,b,c) 

這使我的輸出:

ae= 1 
args = (2, [10, 20]) 

正如你所看到的,a被認爲是一個價值傳遞的ae,並b以及c被認爲是位置參數。

所以,我現在嘗試指派10ae同時呼籲withPositionalArgs

withPositionalArgs(ae=10,b,c) 

但是,我不能這樣做。我得到的錯誤:

SyntaxError: non-keyword arg after keyword arg 

我的問題是:

我是不是做正確?在python函數的位置參數之前是否允許使用默認參數或者使用好實踐?

+2

你可以用'withPositionalArgs稱之爲(10,B,C)'。 –

+0

「令人驚訝」的是調用...(1,ae = 2)拋出TypeError:...()爲關鍵字參數'ae''獲取了多個值。 –

回答

9

在Python2中,不允許在位置參數之前放置具有默認值的參數。

位置參數必須先出現,然後是帶有默認值(或調用函數時,關鍵字參數)的參數,然後*args,然後**kwargs

該順序對於函數定義和函數調用都是必需的。

在Python3中,訂單已放寬。 (例如,*args可以在函數定義中的關鍵字參數之前出現。)See PEP3102

+0

@unubtu:在定義和函數調用中都不允許?或只在一個地方? – GodMan

+0

這是定義和函數調用必須使用的順序。雖然在函數調用中,你可以做'foo(c = 1,ae = 3,b = 2)'。也就是說,參數的順序可以通過提供關鍵字參數來混亂。 – unutbu

+0

這似乎很愚蠢,但是,Vaughn Cato對我的回答的評論允許我根據需要傳遞參數a,並且python不會給出任何錯誤。那麼,我應該修改你的答案: '在Python中,在函數調用中,不允許在位置參數之前放置具有缺省參數的參數。但是,你可以在函數定義中這樣做? – GodMan

2

我認爲我們應該區分默認值與任意參數/鍵值對的傳遞。但沒有默認值的行爲是一樣的:

def f(ae,*args, **kwargs): 
    print 'ae  = ', ae 
    print 'args = ', args 
    print 'kwargs = ', kwargs 

我們寫這意味着在元組args傳遞到f的第一個參數,即f(1,2,3,a=1,b=2)的方式(順序就明確的參數,* ARGS,** kwargs。)這裏:ae = 1, args = (2,3), kwargs = {'a': 1, 'b': 2}

如果我們試圖通過f(1,2,3,a=1,ae=3)我們拋出TypeError: f() got multiple values for keyword argument 'ae',因爲ae的值試圖改變兩次。

。解決此

一種方式是隻設置ae當明確規定,我們可以(後DEF線):

def g(*args, **kwargs): 
    kwargs, kwargs_temp = {"ae": 9}, kwargs 
    kwargs.update(kwargs_temp) #merge kwargs into default dictionary 

,這一次g(1,2,3,a=1,ae=3)args=(1,2,3), kwargs={a=1,ae=3}

但是,我懷疑這不是最佳實踐...

1

Python3輕鬆訂購。

現在你可以這樣做:

def withPositionalArgs(*args, ae=9): 
    print('ae=', ae) 
    print('args =', args) 
a=1 
b=2 
c=[10, 20] 
withPositionalArgs(a, b, c, ae=7)