2017-06-19 9 views
0

Ich möchte einen Lambda-Ausdruck "nach innen schauen", ohne ihn zu bewerten. einen Ausdruck wie der hier gegebenenIntrospektion von Lambda-Ausdrücken

(lambda something: something.x > something.y) 

ich die Elemente zugreifen möchten, die außerhalb des lambda zugegriffen werden. (Dh eine Liste mit Verweisen auf something.x und something.y zurückzukehren.

Doch wie meine Ausdrücke können Nebenwirkungen haben, (lambda self: self.set_value(15)) Ich möchte, dies zu tun, ohne den Ausdruck tatsächlich aufgerufen wird. Führt zum Erlöschen dieser Anforderung die Möglichkeit __getattr__ außer Kraft zu setzen in das Objekt, das in die lambda geben wird

kurzes Beispiel:.

l = (lambda something: something.x > something.y) 
something = Something() 
elements = l.get_accessed_elements(something) 
# elements is a list where 
# elements[0] points to something.x, and 
# elements[1] points to something.y 

ich schaute in den Körper selbst Parsen, aber ich würde eine Schnur Magie Zugriff haben, um den Quellcode und tun, um die Quelle zu reinigen -li nes (gesammelt über inspect).

+5

ich wirklich verstehe nicht, was du zu tun versuchst. Kannst du ein konkretes Beispiel erklären? –

+0

Möchten Sie herausfinden, dass auf 'x' und' y' von dem Objekt zugegriffen wird, das als 'something' bezeichnet wird, ohne den Code für die Lambda-Funktion zu haben? Wenn ja, könnten Sie versuchen, die '__getattr__' Methode in der Definition der Klasse zu überschreiben, von der' irgendwas' eine Instanz ist. – inspectorG4dget

+0

'Lambda etwas: Druck (etwas) oder etwas.x> etwas.j' –

Antwort

1

Sie konnten die zerlegten Bytecode zugreifen, obwohl, ich glaube, diese Sichtprüfung erfordern würde:

>>> import dis 
>>> dis.dis((lambda something: something.x > something.y)) 
    1   0 LOAD_FAST    0 (something) 
       3 LOAD_ATTR    0 (x) 
       6 LOAD_FAST    0 (something) 
       9 LOAD_ATTR    1 (y) 
      12 COMPARE_OP    4 (>) 
      15 RETURN_VALUE 
>>> 

Sie dies auch programmatisch tun kann, etwas in der Art von:

>>> bc = dis.Bytecode(lambda something: something.x > something.y) 
>>> for instr in bc: 
...  if instr.opname == "LOAD_ATTR": 
...   print(instr.argval) 
... 
x 
y 
>>> 
+0

@ S.K. Nur damit Sie wissen, der Wert, den Sie von 'LOAD_ATTR' erhalten, entspricht möglicherweise nicht dem Argument, das an das Lambda übergeben wird, obwohl' Lambda'-Funktionen wirklich nicht so komplex sein sollten, aber es ist eine Möglichkeit. Verdammt, alles geht, wenn dein 'lamda' mögliche Nebenwirkungen haben könnte :: shudders :: –

2

Das hat eigentlich nichts mit Lambda-Ausdrücken zu tun. Aber wenn Sie versuchen, zu sehen, welches Attribut zugegriffen werden, können Sie immer eine benutzerdefinierte Klasse mit einer __getattribute__ Methode definieren, die ihre Argumente drucken:

class Something(object): 
    def __getattribute__(self, name): 
     print("{} was accessed".format(name)) 

Wenn Sie nun, dass auf Ihren Lambda-Ausdruck übergeben:

>>> l = lambda something: something.x > something.y 
>>> s = Something() 
>>> l(s) 
x was accessed 
y was accessed 

bearbeiten nach Kommentar Es ist vielleicht nicht in allen Fällen funktionieren, aber die Attribute des __code__ Attribut des Lambda-Untersuchung zeigt eine co_names Attribut, das ('x', 'y') enthalten passiert. Keine Ahnung, ob das für dich genug ist.

+0

Ich dachte daran, so etwas zu tun. Das Problem besteht jedoch darin, dass das Lambda Nebenwirkungen haben könnte (z. B. "something.x.setValue (15)"), so dass ein nicht-intrusiver Weg (d. H. Kein tatsächliches Ausführen) vorzuziehen wäre. – stklik

+0

@ S.K. Wie konntest du die Identität von etwas erkennen, ohne das "Lambda" zu nennen? Sie müssen wirklich Ihre Frage genau mit dem klären, was Sie suchen. –

+0

@ juanpa.arrivillaga im Grunde @ Daniel-Rosemans Antwort wäre die halbe Lösung. Ich könnte/update/eine Liste von 'something' Elementen erhalten, auf die zugegriffen wird.Dazu müsste ich jedoch das 'lambda' aufrufen, das den Code ausführen würde. Aber das könnte/würde in vielen Fällen den Zustand des Systems verändern. Erklärt das mein Problem? Ich dachte an einen Parsing-Ansatz, aber mein Python-Wissen ist nicht gut genug. – stklik

Verwandte Themen