def f(a, b, *args):
return (a, b, args)
f(a=3, b=5)
(3, 5,())
f(a=3, b=5, *[1,2,3])
TypeError: got multiple values for argument 'b'
爲什麼它的行爲這樣的嗎?
有什麼特別的原因?
def f(a, b, *args):
return (a, b, args)
f(a=3, b=5)
(3, 5,())
f(a=3, b=5, *[1,2,3])
TypeError: got multiple values for argument 'b'
爲什麼它的行爲這樣的嗎?
有什麼特別的原因?
在文檔for calls:
If the syntax
*expression
appears in the function call, expression must evaluate to an iterable. Elements from these iterables are treated as if they were additional positional arguments. For the callf(x1, x2, *y, x3, x4)
, ify
evaluates to a sequencey1, ..., yM
, this is equivalent to a call withM+4
positional argumentsx1, x2, y1, ..., yM, x3, x4
.
而且,這是其次:
A consequence of this is that although the
*expression
syntax may appear after explicit keyword arguments, it is processed before the keyword arguments (and any**expression arguments
– see below).
(重點煤礦)
所以Python會先處理*args
的位置參數,分配值設置爲b
,並將其重新分配給b=5
,導致關鍵字參數的錯誤爲m多重值。
問題是關鍵字。關鍵字參數後面不允許使用位置參數。
f(3, 5, *[1,2,3])
工作正常,因爲它傳遞一個元組與值1,2,3。同爲:
f(3, 5, *(1,2,3))
關鍵詞必須總是放在位置參數之後,所以它是你的函數聲明這是不正確的:
def f(*args, a, b):
return (a, b, args)
print(f(a=3, b=5))
print(f(*[1,2,3], a=3, b=5))
給出:
(3, 5,())
(3, 5, (1, 2, 3))
有趣的是,除了給出「在Python 2.7中爲關鍵字參數「a」獲得了多個值,並且在python 3.5中獲得了多個值「b'」 – cdarke
@cdarke當使用關鍵字參數時,會發生什麼是python會生成一個'd ict'來存儲這些參數。 '字典沒有可靠的順序。錯誤信息的差異反映了這一點:使用python2.7它發生了這樣的情況:在python3.5中,'a'是第一個要迭代的關鍵字,它恰好是'b'。但它完全取決於如何建立字典等。 – Bakuriu
@Bakuriu:我意識到這一點,但我覺得應該有一些努力獲得一致和有用的錯誤消息,無論內部實現。 「真正」的問題是在位置參數之前使用關鍵字,這就是應該檢測和報告的錯誤。 – cdarke