2017-02-20 2 views
1
alist = [] 
def show(*args, **kwargs): 
     alist.append(*args, **kwargs) 
     print(alist) 


>>> show('tiger') 
['tiger'] 
>>> show('tiger','cat') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (2 given) 
>>> show('tiger','cat', {'name':'tom'}) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (3 given) 

Da die Methode append von Alist akzeptiert nur ein Argument, warum nicht einen Syntaxfehler in der Zeile alist.append(*args, **kwargs) in der Definition der Methode zu erkennen?Wie funktioniert das list.append?

+1

, denn das ist nicht, wie Python funktioniert .. Da ist nichts syntaktisch falsch, die Funktion tut es einfach Es akzeptiert nicht mehr als 1 Argument. Versuchen Sie list.extend – user2682863

+6

Wie soll der Interpreter wissen, was "Alist" sein wird, wenn Sie 'show' aufrufen? – TigerhawkT3

+0

Wolltest du fragen, warum es keinen Fehler für 'show ('tiger')' gab, aber gab es für 'show ('tiger', 'cat')'? –

Antwort

2

Es ist kein Syntaxfehler, weil die Syntax vollkommen in Ordnung ist und diese Funktion einen Fehler verursachen kann oder nicht, je nachdem, wie Sie ihn aufrufen.

So wie du es bist Aufruf:

alist = [] 
def show(*args, **kwargs): 
    alist.append(*args, **kwargs) 
    print(alist) 

>>> show('tiger') 
['tiger'] 
>>> show('tiger','cat') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 2, in show 
TypeError: append() takes exactly one argument (2 given) 

Eine andere Art und Weise:

alist = [] 
def show(*args, **kwargs): 
    alist.append(*args, **kwargs) 
    print(alist) 

>>> show('tiger') 
['tiger', 'tiger'] 
>>> class L: pass 
... 
>>> alist = L() 
>>> alist.append = print 
>>> show('tiger','cat') 
tiger cat 
<__main__.L object at 0x000000A45DBCC048> 
0

Es ist nicht ein Syntaxfehler, weil es zur Laufzeit aufgelöst. Syntaxfehler werden anfänglich zur Interpretierzeit abgefangen, wenn Sie so wollen. Dinge wie unübertroffene Klammern, undefinierte Variablennamen, fehlende Argumente (dies ist kein fehlendes Argument * Argumente bedeuten eine beliebige Anzahl von Argumenten).

show hat keine Möglichkeit zu wissen, was Sie es zur Laufzeit übergeben werden und da Sie Ihre args Variable innerhalb show erweitern, könnte es eine Reihe von Argumenten auf sich warten lassen und es ist eine gültige Syntax! list.append braucht ein Argument! Eine tuple, eine list, eine int, Zeichenfolge, benutzerdefinierte Klasse usw. usw. Was Sie passieren, ist einige Zahlenelemente abhängig am Eingang. Wenn Sie das * entfernen, ist es alles Dandy als sein ein Element, z. alist.append(args).

All dies bedeutet, dass Ihre show Funktion fehlerhaft ist. Es ist ausgestattet, um args nur zu behandeln, wenn es der Länge 1 ist. Wenn es 0 ist, erhalten Sie auch einen TypeError, an dem Punkt append aufgerufen wird. Wenn es mehr als das ist gebrochen, aber Sie werden nicht wissen, bis Sie es mit der schlechten Eingabe ausführen.

Sie können die Elemente in args (und kwargs) durchlaufen und sie einzeln hinzufügen.

alist = [] 
def show(*args, **kwargs): 

    for a in args: 
     alist.append(a) 
    for kv in kwargs.items(): 
     alist.append(kv) 

    print(alist) 
1

Python-Objekte sind stark typisiert. Die Namen, die an sie binden, sind nicht. Es gibt auch keine Funktionsargumente. Angesichts der dynamischen Natur von Python wäre es extrem schwierig, den Typ einer Variablen an einem gegebenen Quellort zur Ausführungszeit statisch vorherzusagen, so dass die allgemeine Regel ist, dass Python es nicht ausprobiert. In Ihrem spezifischen Beispiel ist alist nicht im lokalen Bereich. Daher kann es geändert werden nach Ihre Funktionsdefinition wurde ausgeführt und die Änderungen werden für Ihre Funktion sichtbar sein, vgl. Codeschnipsel unten. Also, in Übereinstimmung mit der allgemeinen Regel: Vorhersage, ob alist eine Liste sein wird, wenn Sie .append aufrufen? Fast unmöglich. Insbesondere kann der Interpreter nicht vorhersagen, dass dies ein Fehler sein wird.

Hier ist ein Code, nur um den Punkt nach Hause zu bringen, dass die statische Typüberprüfung in Python praktisch unmöglich ist. Es verwendet nicht-lokale Variablen wie in Ihrem Beispiel.

funcs = [] 
for a in [1, "x", [2]]: 
    def b(): 
     def f(): 
      print(a) 
     return f 
    funcs.append(b()) 

for f in funcs: 
    f() 

Ausgang:

[2] # value of a at definition time (of f): 1 
[2] # value of a at definition time (of f): 'x' 
[2] # value of a at definition time (of f): [2] 

Und in ähnlicher Weise für nicht-globale nicht-lokale Variablen:

funcs = [] 
for a in [1, "x", [2]]: 
    def b(a): 
     def f(): 
      print(a) 
     a = a+a 
     return f 
    funcs.append(b(a)) 

for f in funcs: 
    f() 

Ausgang:

2  # value of a at definition time (of f): 1 
xx  # value of a at definition time (of f): 'x' 
[2, 2] # value of a at definition time (of f): [2]