Meine Absicht ist es, ein Wörterbuch zu erstellen, dessen Schlüssel Primitive sind und deren Werte Null-Argument-Funktionen sind, die Strings zurückgeben. (Dies ist Teil eines größeren Projekts zum Implementieren einer VM.) Einige dieser Funktionen sind nicht trivial und werden manuell erstellt und zugewiesen. Die funktionieren gut. Andere scheinen jedoch der automatischen Erzeugung zugänglich zu sein.Wie erzwinge Python3 nach Wert übergeben?
Mein erster Versuch fehlgeschlagen:
>>> regs = ['a', 'b', 'c', 'x', 'y', 'z']
>>> vals = {i : lambda: r for i, r in enumerate(regs)}
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
OK, fein; Die Lambda-Funktion liest r nicht, bis sie aufgerufen wird. Ich versuchte es noch einmal und versucht, einen Wert für sich allein zu isolieren:
>>> from copy import copy
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... r = copy(reg) # (1)
... vals[i] = lambda: r
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
(1) ich diesen Schritt gedacht, eine unabhängige Variable erstellen, die sich nicht ändern würde, wenn reg tat. Das ist nicht der Fall.
So hat dieser Versuch eindeutig nicht funktioniert. Vielleicht ist die Kopie an einer Schnur ein Noop?
>>> 's' is 's'
True
>>> a = 's'
>>> b = copy(a)
>>> a is b
True
>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a is b
True
Richtig. Kopieren an einer Schnur ist ein Noop. Deepcopy repariert das nicht. Folglich hat das Lambda immer noch einen Verweis auf die Variable, die in jeder Schleife aktualisiert wird, was diesen Fehler verursacht.
Wir brauchen einen anderen Ansatz. Was passiert, wenn ich die Variable, die ich möchte, in eine statische Variable der temporären Funktion speichere? Das sollte funktionieren, wenn jede temporäre Funktion ihre eigene Identität bekommt ...
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... def t():
... return t.r
... t.r = reg
... vals[i] = t
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
Nein. An diesem Punkt bin ich kurz davor, alles nur manuell zu behandeln:
>>> vals = {}
>>> vals[0] = lambda: 'a'
>>> vals[1] = lambda: 'b'
... und so fort. Das fühlt sich jedoch an, als ob man aufgibt und wird unglaublich langweilig werden. Gibt es einen richtigen phytonischen Weg, um diese Aufgabe zu erfüllen? Einer der Gründe, warum ich Python normalerweise liebe, ist, dass ich mich von der manuellen Zeigerverwaltung fern halte; Ich hätte mir nie vorstellen können, dass ich mir wünschen würde, dass es eine ganze Reihe von Zeigerwerkzeugen enthält!
Danke! Das Einstellen von Standardparametern ist für mich viel sinnvoller, als alles über eine make_const-Funktion zu tun, zumindest soweit ich weiß, wie es funktioniert. Ich nehme an, dass es keinen signifikanten Unterschied in der Leistung zwischen den zwei Methoden gibt? – coriolinus
@coriolinus Es sollte keinen signifikanten Unterschied geben. Wenn es da ist, gibt es wahrscheinlich viele größere Fische, bevor es zum Flaschenhals wird. Und an diesem Punkt sollten Sie wahrscheinlich nur in den sauren Apfel beißen, Ihren Code [RPython] (http://morepypy.blogspot.de/2011/04/tutorial-writing-interpreter-with-pypy.html) erstellen und eine Kompilierung machen C, ein JIT-Compiler und eine Reihe von guten GCs fast kostenlos. – delnan