Python-Begriffe und Formulierungen sind ziemlich verdächtig.
TLTR
Ich habe einen Artikel über die Bewertung der Python-Verzögerung gelesen und zusammengefasst.
Python kann Standardargumente festlegen. ** Die Standardargumente der Funktion werden jedoch bei der Definition der Funktion ausgewertet. Nicht zur Laufzeit. Es ist eine unerwartete Gefahr, wenn Sie die Spezifikation von ** nicht kennen.
Definieren Sie eine append_to-Funktion, die nur die übergebenen Argumente zur Liste hinzufügt. Es hat standardmäßig eine leere Liste.
Anhängen, um der Liste ein Argument hinzuzufügen_Funktionieren
>>> def append_to(element, to=[]):
... to.append(element)
... return to
...
Fügen wir 12,42 hinzu. Weil es ein Argument "to = []" gibt [12] [42] Es scheint so als.
>>> my_list = append_to(12)
>>> print(my_list)
[12]
>>> my_other_list = append_to(42)
>>> print(my_other_list)
[12, 42]
Es ist nicht das, was du erwartet hast. Was bedeutet das.
Das Standardargument to ist definiert als to = []
.
Wir werden den Wert hier nacheinander aktualisieren.
Wenn "to = []" im Prozess des Werdens zu "to = []" -> "to = [12]" -> "to = [12,42]" ausgewertet wird,
to = []
-> to = [12]
-> to = []
-> to = [42]
, was das gewünschte Ergebnis zu liefern scheint, aber ** das Standardargument ist eine Funktion Es wird zum Zeitpunkt der Definition bewertet. ** **.
Mit anderen Worten, to ist "to = []", wenn eine Funktion definiert wird, aber ** tut nicht "to = []" jedes Mal, wenn sie aufgerufen wird **, also wenn "appent_to (42)", "to = [12] Es bedeutet, dass es bleibt.
Was ist stattdessen zu tun? Es scheint, dass "to = None" gemacht werden sollte.
Es fühlt sich ein wenig überflüssig an. Ich weiß nicht was ich tun soll.
def append_to(element, to=None):
if to is None:
to = []
to.append(element)
return to
my_list = append_to(12)
print(my_list)
my_other_list = append_to(42)
print(my_other_list)
[12]
[42]
Ich habe das gewünschte Ergebnis erzielt.
Python kann faul auswerten. Grob gesagt bedeutet verzögerte Bewertung, bei Bedarf zu bewerten.
Wenn Sie ein Anfänger wie ich sind, der normalerweise Python lernt, lautet dies "Ich weiß! Dies ist der, den ich im ** Seminar gesehen habe".
Wenn Sie von nun an mittelgroßen Code schreiben möchten, müssen Sie zwangsläufig die Standardargumente der Funktion entwerfen.
Es gibt jedoch eine solche Python-Spezifikation.
** Variable Bindung beim Verschluss wird verzögert ausgewertet **
Schauen wir uns ein Codebeispiel an, das einen sogenannten Abschluss verwendet, bei dem Werte in einer Funktion gespeichert werden.
Das Ziel ist Code, der eine Liste mit dem Inhalt der Liste multipliziert mit dem Wert des Arguments zurückgibt.
Ein Skript, das eine Liste mit dem Inhalt der Liste multipliziert mit dem Wert des Arguments zurückgibt
functions = []
for n in [1, 2, 3]:
def func(x):
return n * x
functions.append(func)
# You would expect this to print [2, 4, 6]
print('{}'.format(str([function(2) for function in functions])))
Es scheint, dass "[2, 4, 6]([1 * 2, 2 * 2, 3 * 2])" ausgegeben wird, aber ...
python
[6, 6, 6]
Wurde ausgegeben.
Python-Verschlüsse werden aufgeschoben ausgewertet. Die Werte der im Abschluss verwendeten Variablen werden zum Zeitpunkt ihres Aufrufs ebenfalls referenziert.
Daher ist n nicht zu dem Zeitpunkt festgelegt, zu dem der Abschluss in der for-Anweisung aufgerufen wird, und es wird in "Funktionen" im Zustand "n * x" gespeichert. Sozusagen "[n * x, n * x, n * x]"
Wenn es von der print-Anweisung ausgeführt wird, wird daher auf den letzten Zustand von n, n == 3
, verwiesen, also[6,6,6]([3 * 2,3 * 2,3 * 2) ], X = 2)
.
Verwenden Sie den Debugger, um die Reihenfolge der Aktualisierung der Werte der for- und print-Anweisungen anzuzeigen.
Da der Wert der Variablen n durch die Iteration auf bereits 3 aktualisiert wurde, wird die Funktion durch Druck die ganze Zeit n == 3 ausgewertet. Sie können aus dem Druck ersehen, dass n == 3 dreimal referenziert wird.
Es ist schwer zu verstehen, also werde ich einen anderen posten.
Ändern Sie das Abschlussargument von "x" in "x, n = n". Das Problem wird gelöst, indem der Wert von n übergeben wird, dh der Wert von n an die Funktionen übergeben wird, die den Abschluss jedes Mal speichern, wenn er mit einer for-Anweisung wiederholt wird.
Fügen Sie dazu den Wert von n in das Argument ein, z. B. "def func (x, n = n):", und lassen Sie es die Form einer Neuzuweisung annehmen. Dies ermöglicht es dem Abschluss, den Wert von n aus der Spezifikation des Haltens des Werts innerhalb dieser Funktion zu aktualisieren.
Ein Skript, das eine Liste mit dem Inhalt der Liste multipliziert mit dem Wert des Arguments zurückgibt
functions = []
for n in [1, 2, 3]:
def func(x, n=n):# n=Hinzugefügt n.
# def func(x):
return n * x
functions.append(func)
print('{}'.format(str([function(2) for function in functions])))
Ausgabeergebnis
[2,4,6]
Werfen wir einen Blick auf den Debugger.
Ich frage mich, ob das Verhalten von func mit dem Debugger gut ausgedrückt werden kann, aber ich konnte dafür sorgen, dass es sich wie erwartet verhält.
Es scheint, dass Sie die Bibliothek verwenden sollten. Diesmal wird es weggelassen.
from functools import partial
from operator import mul
Python führt eine faule Auswertung durch. Dies ist etwas verwirrend, wenn Sie regelmäßig prozedurale Programme programmieren. Es ist eine Funktion, die aus einer funktionalen Sprache stammt, also etwas eigenartig.
Ich bin nicht sicher, wie ich die Variablenbindung (Zuweisung in einer funktionalen Sprache) in Python richtig verwenden soll. </ del>
Es gab einen Punkt im Kommentar.
Ich habe in Beispiel 1 geschrieben, dass Pythons Standardargumente aufgeschoben ausgewertet werden. Dies war jedoch ein falsches Verständnis. Das Standardargument von Python ist eine Spezifikation, die gebunden wird, wenn eine Funktion deklariert wird, anstatt verzögert ausgewertet und gebunden zu werden. Es scheint korrekter zu sein, sich nicht intuitiv zu verhalten, wie in Beispiel 1.
https://ja.coder.work/so/python/1087272 https://python-guideja.readthedocs.io/ja/latest/writing/gotchas.html https://stackoverflow.com/questions/36463498/late-binding-python-closures
Recommended Posts