2016-07-07 30 views
5
def f(a, b, *args): 
    return (a, b, args) 

f(a=3, b=5) 
(3, 5,()) 

während:Python 3.5 Typeerror: got mehrere Werte für Argument

f(a=3, b=5, *[1,2,3]) 
TypeError: got multiple values for argument 'b' 

Warum es so verhält?
Irgendein besonderer Grund?

+1

Interessant, die Ausnahme gibt " hat mehrere Werte für das Schlüsselwortargument 'a' "in Python 2.7 und" hat mehrere Werte für das Argument 'b' "in python 3.5 – cdarke

+0

@cdarke Bei der Verwendung von Schlüsselwortargumenten passiert, dass Python ein' d erstellt ict', um diese Argumente zu speichern. 'dict's haben keine verlässliche Reihenfolge. Der Unterschied in der Fehlermeldung spiegelt dies wider: Mit python2.7 passiert es, dass der Hash so erstellt wird, dass "a" der erste Schlüssel ist, der über iteriert wird, während er auf python3.5 mit "b" passiert. Aber es hängt vollständig davon ab, wie das Wörterbuch aufgebaut ist usw. – Bakuriu

+0

@Bakuriu: Ich war mir dessen bewusst, aber ich denke, dass es einige Bemühungen geben sollte, um eine konsistente und hilfreiche Fehlermeldung zu erhalten, unabhängig von der internen Implementierung. Das "echte" Problem ist die Verwendung von Schlüsselwörtern vor Positionsargumenten, und das ist der Fehler, der erkannt und gemeldet werden sollte. – cdarke

Antwort

5

In der Dokumentation 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 call f(x1, x2, *y, x3, x4) , if y evaluates to a sequence y1, ..., yM , this is equivalent to a call with M+4 positional arguments x1, x2, y1, ..., yM, x3, x4 .

Und wird dies durch gefolgt:

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).

(Hervorhebung von mir)

So Python zuerst das *args als Positionsargument verarbeitet, zuordnen Wert auf b und neu zuweisen mit b=5 was zu einem Fehler für das Schlüsselwortargument mit m führt multiple Werte.

0

Das Problem sind die Schlüsselwörter. Sie dürfen keine Positionsargumente nach Schlüsselwortargumenten verwenden.

f(3, 5, *[1,2,3]) 

funktioniert gut, dass es eine übergibt Tupel mit den Werten 1,2,3. Das gleiche wie:

f(3, 5, *(1,2,3)) 

Keywords muss immer kommen, nachdem Positionsargumente, so ist es Ihre Funktionsdeklaration, die falsch ist:

def f(*args, a, b): 
    return (a, b, args) 

print(f(a=3, b=5)) 
print(f(*[1,2,3], a=3, b=5)) 

Gibt:

(3, 5,()) 
(3, 5, (1, 2, 3))