2009-07-26 13 views
11

Non sono sicuro di cosa intendo qui, quindi per favore portami con me ..Passando le espressioni alle funzioni in python?

In sqlalchemy, sembra che dovrei passare un'espressione? a filter() in alcuni casi. Quando provo a implementare qualcosa di simile me, io alla fine con:

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

>>> someFunc(5 == 5) 
True 

Come faccio ad avere i valori passati a == dal all'interno della funzione?

Edit: Sto cercando di realizzare qualcosa di simile

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

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

Edit: Che dire se una delle paramaters era un oggetto?

+0

Follow-up domanda circa i ORM: http://stackoverflow.com/questions/1185537 –

risposta

21

È possibile ottenere il vostro esempio se si fanno "op" una funzione:

 
    >>> 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 

Questo è più Pythonic di superamento di un Stringa. È come funzionano le funzioni come sort().

Questi esempi SQLAlchemy con filter() sono sconcertanti. Non conosco i componenti interni di SQLAlchemy, ma sto cercando di indovinare in un esempio come query.filter (User.name == 'ed'). Quello che succede è che User.name è un tipo specifico di SQLAlchemy, con uno strano implementazione della funzione __eq() che genera SQL per la funzione filter() invece di fare un confronto. Ad esempio: hanno creato classi speciali che consentono di digitare espressioni Python che emettono codice SQL. È una tecnica insolita, una che eviterei a meno di costruire qualcosa che colleghi due lingue come un ORM.

+0

Si noti che non è necessario parentesi lambda. –

+3

Vero, ma metterlo tra parentesi rende più facile leggere in questo caso a causa dei parametri interni del lambda. –

+0

Se ti piace, sono solo parenti superflui per me. –

1

Non è possibile. L'espressione 5 == 5 viene valutata e solo allora il risultato viene passato a someFunc. La funzione diventa semplicemente True (l'oggetto True, per la precisione), indipendentemente dall'espressione.

Modifica: Per quanto riguarda la modifica, this question è un tipo di chiusura.

Edit 2: Si potrebbe semplicemente passare l'espressione come una stringa e utilizzare eval, in questo modo:

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

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

Non so se si può dire. Tieni presente che eval è uno strumento potente, quindi è pericoloso trasmettere input arbitrario (e possibilmente anche generato dall'utente).

0

È necessario avvolgere il tutto come una stringa letterale. Stai cercando di stamparlo come una stringa che presumo, corretto?

0

Risposta breve: non è possibile. Il risultato della valutazione dell'espressione viene passato alla funzione piuttosto che all'espressione stessa.

1

Sembra che tu puoi tornare tuple da eq:

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

È possibile restituire tutto ciò che si desidera da '__eq__', ma restituire qualcosa che non può essere forzato a un bool per confrontare l'uguaglianza - lo scopo di' __eq__' - è una pessima idea. –

+0

Probabilmente è una cattiva pratica, ma questa è comunque una domanda teorica. Più di un "come è possibile?" scrivi cosa –

+0

SQLalchemy fa davvero qualcosa del genere? Quella è una libreria che non toccherà con un palo d'acciaio di 20 piedi. È un hack disgustoso. (Non ti attacca, stai solo spiegando come potrebbero averlo fatto.) –

5

Una variante ancora più pitonica della soluzione di Nelson consiste nell'utilizzare le funzioni dell'operatore dal modulo operator nella libreria standard; non è necessario creare il tuo lambda.

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

È necessario implementare __eq__(). Per esempio ::

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

Poi, per la funzione che si desidera ottenere l'espressione, come ::

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

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