2009-07-26 5 views
11

Ich bin nicht ganz sicher, was ich hier meine, also bitte bitte mit mir ..Übergeben von Ausdrücken an Funktionen in Python?

In sqlalchemy, es scheint, ich soll einen Ausdruck übergeben? in bestimmten Fällen zu filter(). Wenn ich versuche, mich so etwas zu realisieren, habe ich am Ende oben mit:

>>> def someFunc(value): 
... print(value) 

>>> someFunc(5 == 5) 
True 

Wie erhalte ich die übergebenen Werte aus dem Inneren der Funktion ==?

Edit: Ich versuche, so etwas wie diese

>>> def magic(left, op, right): 
... print(left+" "+op+" "+right) 

>>> magic(5 == 5) 
5 == 5 

bearbeiten zu erreichen: Was ist, wenn einer der Paramater ein Objekt ist?

+0

Follow-up-Frage zu den ORMs: http://stackoverflow.com/questions/1185537 –

Antwort

21

Sie erreichen Ihr Beispiel, wenn Sie "op" eine Funktion machen Zeichenfolge. So funktionieren Funktionen wie sort().

Diese SQLAlchemy Beispiele mit filter() sind rätselhaft. Ich kenne die Interna von SQLAlchemy nicht, aber ich vermute in einem Beispiel wie query.filter (User.name == 'ed'), was passiert ist, dass User.name ein SQLAlchemy-spezifischer Typ ist, mit einem ungeraden Implementierung der Funktion __eq(), die SQL für die Funktion filter() generiert, anstatt einen Vergleich durchzuführen. Dh: Sie haben spezielle Klassen erstellt, mit denen Sie Python-Ausdrücke eingeben können, die SQL-Code ausgeben. Es ist eine ungewöhnliche Technik, die ich vermeiden würde, wenn ich nicht etwas baue, das zwei Sprachen wie ein ORM überbrückt.

+0

Beachten Sie, dass Lambda nicht in Klammern gesetzt werden muss. –

+3

Richtig, aber wenn man es in Klammern setzt, ist es in diesem Fall aufgrund der internen Parameter des Lambda leichter zu lesen. –

+0

Wenn Sie mögen - es ist nur überflüssige Parens für mich. –

1

Sie können nicht. Der Ausdruck 5 == 5 wird ausgewertet und erst dann wird das Ergebnis an someFunc übergeben. Die Funktion bekommt gerade True (das True Objekt, um genau zu sein), egal was der Ausdruck war.

Edit: In Bezug auf Ihre Bearbeitung, this question ist irgendwie nah.

Edit 2: Sie konnte nur den Ausdruck als String übergeben und eval verwenden, wie folgt aus:

>>> def someFunc(expression_string): 
... print(expression_string, "evaluates to", eval(expression_string)) 

>>> someFunc("5 == 5") 
5 == 5 evaluates to True 

Sie wissen nicht, ob das Ihnen hilft. Denken Sie daran, dass eval ein mächtiges Werkzeug ist, daher ist es gefährlich, willkürliche (und möglicherweise sogar vom Benutzer generierte) Eingaben an es zu übergeben.

0

Sie müssen das Ganze als eine literale Zeichenfolge umschließen. Du versuchst das als String auszugeben, nehme ich an, richtig?

0

Kurze Antwort: Sie können nicht. Das Ergebnis der Ausdruckbewertung wird an die Funktion und nicht an den Ausdruck selbst übergeben.

1

Es scheint, Sie Tupeln aus eq zurückkehren können:

 
    >>> def magic(left, op, right): 
    ...  return op(left, right) 
    ... 
    >>> magic(5, (lambda a, b: a == b), 5) 
    True 
    >>> magic(5, (lambda a, b: a == b), 4) 
    False 

Das ist mehr Pythonic als ein vorübergehendes:

class Foo: 
    def __init__(self, value): 
      self.value = value 

    def __eq__(self, other): 
      return (self.value, other.value) 


f1 = Foo(5) 
f2 = Foo(10) 
print(f1 == f2) 
+2

Sie können alles zurückgeben, was Sie wollen von '__eq__', aber etwas zurückgeben, das nicht zu einem Bool gezwungen werden kann, um Gleichheit zu vergleichen - der Zweck von' __eq__' - ist eine wirklich schlechte Idee. –

+0

Es ist wahrscheinlich eine schlechte Übung, aber das ist eine theoretische Frage. Mehr von einem "Wie ist das möglich?" Typ Ding. –

+0

SQLalchemie macht wirklich so etwas? Das ist eine Bibliothek, die ich nicht mit einer 20-Fuß-Stahlstange berühren werde. Es ist ein ekelhafter Hack. (Sie nicht anzugreifen - Sie erklären nur, wie sie es getan haben könnten.) –

5

Eine noch pythischere Variante von Nelsons Lösung ist die Verwendung der Operatorfunktionen aus dem operator-Modul in der Standardbibliothek; Es besteht keine Notwendigkeit, eigene Lambdas zu erstellen.

>>> from operator import eq 
>>> def magic(left, op, right): 
... return op(left, right) 
... 
>>> magic(5, eq, 5) 
True 
1

Sie müssen __eq__() implementieren. Zum Beispiel ::

class A(object): 
    def __eq__(self, other): 
     return (self, '==', other) 

Dann wird für die Funktion, die Sie den Ausdruck erhalten möchten, wie ::

def my_func(expr): 
    # deal with the expression 
    print(expr) 

>>> a = A() 
>>> my_func(a == 1) 
(<__main__.A object at 0x1015eb978>, '==', 1)