Python ist meine erste dynamische Sprache. Ich habe kürzlich einen Funktionsaufruf codiert, der falsch eine falsche Anzahl von Argumenten liefert. Dies schlug mit einer Ausnahme zum Zeitpunkt des Aufrufs dieser Funktion fehl. Ich habe erwartet, dass diese Art von Fehler auch in einer dynamischen Sprache erkannt werden kann, wenn die Quelldatei analysiert wird.
Ich verstehe, dass der Typ der tatsächlichen Argumente erst bekannt ist, wenn die Funktion aufgerufen wird, da dieselbe Variable zu unterschiedlichen Zeiten Werte eines beliebigen Typs enthalten kann. Die Anzahl der Argumente ist jedoch bekannt, sobald die Quelldatei analysiert wurde. Es wird sich nicht ändern, während das Programm ausgeführt wird.
Damit dies keine philosophische Frage ist
Lassen Sie mich die Frage so formulieren, um dies im Rahmen des Stapelüberlaufs zu halten. Gibt es eine Funktion, die Python anbietet und die es erfordert, die Überprüfung der Anzahl der Argumente in einem Funktionsaufruf zu verzögern, bis der Code tatsächlich ausgeführt wird?
f(*args)
während der Analysephase nicht bekannt.def foo(): whatever
hatfoo.__name__ == 'foo'
, aber das wird man nicht mehr aufhören zu tun ,foo = some_other_function
oderbar = foo
.Antworten:
Python kann nicht im Voraus wissen, welches Objekt Sie am Ende aufrufen werden, da Sie das Funktionsobjekt austauschen können, da es dynamisch ist . Jederzeit. Und jedes dieser Objekte kann eine andere Anzahl von Argumenten haben.
Hier ist ein extremes Beispiel:
import random def foo(): pass def bar(arg1): pass def baz(arg1, arg2): pass the_function = random.choice([foo, bar, baz]) print(the_function())
Der obige Code hat eine 2: 3-Chance, eine Ausnahme auszulösen. Aber Python kann nicht a priori wissen, ob dies der Fall ist oder nicht!
Und ich habe noch nicht einmal mit dynamischen Modulimporten, der Generierung dynamischer Funktionen, anderen aufrufbaren Objekten (jedes Objekt mit einer
__call__
Methode kann aufgerufen werden) oder Catch-All-Argumenten (*args
und**kwargs
) begonnen.Um dies besonders deutlich zu machen, geben Sie in Ihrer Frage Folgendes an:
Dies ist nicht der Fall, nicht in Python. Sobald das Modul geladen ist, können Sie jedes Objekt im Modul-Namespace löschen, hinzufügen oder ersetzen, einschließlich Funktionsobjekte.
quelle
*
Argumente ... und das ist Python, also ... ja, ziemlich extrem.https://stackoverflow.com/a/34567789
und damit fertig sein.Die Anzahl der übergebenen Argumente ist bekannt, nicht jedoch die tatsächlich aufgerufene Funktion. Siehe dieses Beispiel:
def foo(): print("I take no arguments.") def bar(): print("I call foo") foo()
Dies mag offensichtlich erscheinen, aber lassen Sie uns diese in eine Datei namens "fubar.py" einfügen. Führen Sie nun in einer interaktiven Python-Sitzung Folgendes aus:
>>> import fubar >>> fubar.foo() I take no arguments. >>> fubar.bar() I call foo I take no arguments.
Das war offensichtlich. Nun zum lustigen Teil. Wir definieren eine Funktion, die eine Anzahl von Argumenten ungleich Null erfordert:
>>> def notfoo(a): ... print("I take arguments!") ...
Jetzt machen wir etwas, was man Affenpatching nennt . Wir können tatsächlich die Funktion im Modul ersetzen :
foo
fubar
>>> fubar.foo = notfoo
Wenn wir jetzt anrufen
bar
, wird einTypeError
Wille erhoben; Der Namefoo
bezieht sich jetzt auf die oben definierte Funktion anstelle der ursprünglichen Funktion, die früher als bekannt warfoo
.>>> fubar.bar() I call foo Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/horazont/tmp/fubar.py", line 6, in bar foo() TypeError: notfoo() missing 1 required positional argument: 'a'
Selbst in einer solchen Situation, in der es sehr offensichtlich erscheint, dass die aufgerufene Funktion
foo
keine Argumente akzeptiert, kann Python nur wissen, dass es tatsächlich diefoo
Funktion ist, die aufgerufen wird, wenn diese Quellzeile ausgeführt wird.Dies ist eine Eigenschaft von Python, die es mächtig macht, aber auch einen Teil seiner Langsamkeit verursacht. Tatsächlich wurde vor einiger Zeit auf der Python-Ideen-Mailingliste diskutiert, Module schreibgeschützt zu machen, um die Leistung zu verbessern , aber es wurde keine wirkliche Unterstützung erhalten.
quelle