Ich wollte dies auch in Jython tun. Aber die in der angenommenen Antwort gezeigte Methode funktioniert dort nicht, weil die co_consts
nicht für ein Code-Objekt verfügbar ist. (Außerdem scheint es keine andere Möglichkeit zu geben, ein Code-Objekt abzufragen, um an die Code-Objekte verschachtelter Funktionen zu gelangen.)
Aber natürlich sind die Code-Objekte irgendwo da, wir haben die Quelle und vollen Zugriff, es ist also nur eine Frage der Suche nach einem einfachen Weg innerhalb einer angemessenen Zeit. Also hier ist eine Möglichkeit, die funktioniert. (Halten Sie Ihre Sitze.)
Angenommen, wir haben Code wie folgt in Modul mod
:
def outer():
def inner():
print "Inner"
zuerst den Code Objekt der äußeren Funktion erhalten direkt:
code = mod.outer.__code__
In Jython, Dies ist eine Instanz von PyTableCode
, und durch das Lesen der Quelle finden wir, dass die tatsächlichen Funktionen in einer Java-Klasse implementiert sind, die aus Ihrem gegebenen Skript besteht, auf das durch das Feld funcs
des Codeobjekts verwiesen wird. (Alle diese Klassen, die aus Skripten bestehen, sind Unterklassen von PyFunctionTable
, daher ist das der deklarierte Typ von funcs
.) Dies ist von Jython aus nicht sichtbar, als Folge einer magischen Maschinerie, mit der ein Designer angibt, dass Sie auf diese zugreifen Dinge auf eigenes Risiko.
Also müssen wir für einen Moment in das Java eintauchen. Eine Klasse wie folgt funktioniert der Trick:
import java.lang.reflect.Field;
public class Getter {
public static Object getFuncs(Object o)
throws NoSuchFieldException, IllegalAccessException {
Field f = o.getClass().getDeclaredField("funcs");
f.setAccessible(true);
return f.get(o);
}
}
Zurück in Jython:
>>> import Getter
>>> funcs = Getter.getFuncs(mod.outer.__code__)
>>> funcs
[email protected]
Nun, dies funcs
Objekt alle Funktionen erklärt überall im Jython Skript hat (die beliebig verschachtelt, innerhalb von Klassen, etc.). Außerdem enthält es Felder, die die entsprechenden Code-Objekte enthalten.
>>> fields = funcs.class.getDeclaredFields()
In meinem Fall das Codeobjekt an die verschachtelte Funktion entspricht, ist nun mal die letzte sein:
>>> flast = fields[-1]
>>> flast
static final org.python.core.PyCode mod$py.inner$24
den Code Objekt von Interesse zu erhalten:
>>> flast.setAccessible(True)
>>> inner_code = flast.get(None) #"None" because it's a static field.
>>> dir(inner_code)
co_argcount co_filename co_flags co_freevars co_name co_nlocals co_varnames
co_cellvars co_firstlineno
Und die Rest ist das gleiche wie die akzeptierte Antwort, dh überprüfen Sie co_freevars
, (das ist in Jython, im Gegensatz zu co_consts
).
Eine gute Sache über diesen Ansatz ist, dass Sie genau alle Code-Objekte aufzählen, die irgendwo innerhalb der Quellcode-Datei deklariert sind: Funktionen, Methoden, Generatoren, ob sie unter oder unter einander verschachtelt sind. Es gibt keinen anderen Ort, an dem sie sich verstecken könnten.
Was versuchst du genau zu machen? – kpie
Dies ist ein [XY Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) in großem Maßstab. Wenn Sie sich Sorgen über verspätete Schließungen in einem Stück Code machen, rewrite den Code nicht darunter leiden, tun Sie keine massive Versuch-außer-Stil-Sache nach der Tat. Haben Sie keine Kontrolle über den Code, der dies möglicherweise tun könnte? –
Auch Leute haben nach [spätbindenden Schließungen vorher] gefragt (http://stackoverflow.com/questions/6035848/python-closure-not-working-as-expected) und haben Antworten erhalten, die helfen, dasselbe zu verringern. Folgender Anzug würde dir besser dienen als dein gegenwärtiger Ansatz. –