2009-07-26 9 views
11

No estoy muy seguro de lo que quiero decir aquí, así que por favor tengan paciencia conmigo ..Pasando expresiones a funciones en python?

En sqlalchemy, parece que tengo que pasar una expresión? a filter() en ciertos casos. Cuando trato de poner en práctica algo así a mí mismo, termino con:

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

>>> someFunc(5 == 5) 
True 

¿Cómo consigo los valores pasados ​​a == desde el interior de la función?

Editar: Estoy tratando de lograr algo como esto

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

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

Editar: ¿Qué pasa si uno de los parametros era un objeto?

+0

Seguimiento pregunta sobre los ORM: http://stackoverflow.com/questions/1185537 –

Respuesta

21

Usted puede lograr su ejemplo si haces "op" una función:

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

Esto es más Pythonic de pasar una Cuerda. Así es como funcionan las funciones como sort().

Los ejemplos de SQLAlchemy con filtro() son desconcertantes. No conozco los aspectos internos de SQLAlchemy, pero supongo que en un ejemplo como query.filter (User.name == 'ed') lo que sucede es que User.name es un tipo SQLAlchemy-specific, con un código impar implementación de la función __eq() que genera SQL para la función filter() en lugar de hacer una comparación. Es decir: han creado clases especiales que te permiten escribir expresiones de Python que emiten código SQL. Es una técnica inusual, una que evitaría a menos que se construya algo que vincule dos idiomas, como un ORM.

+0

Tenga en cuenta que no hay necesidad de paréntesis de lambda. –

+3

Es cierto, pero ponerlo entre paréntesis hace que sea más fácil de leer en este caso debido a los parámetros internos de la lambda. –

+0

Si lo desea, es solo parientes superfluos para mí. –

1

No puede. Se evalúa la expresión 5 == 5 y solo entonces se pasa el resultado a someFunc. La función simplemente obtiene True (el objeto True, para ser precisos), sin importar cuál sea la expresión.

Editar: Con respecto a su edición, this question es como de cerca.

Edición 2: Se podía pasar a la expresión como una cadena y usar eval, así:

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

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

no saben si eso le ayuda. Tenga en cuenta que eval es una herramienta poderosa, por lo que es peligroso pasarle una entrada arbitraria (y posiblemente incluso generada por el usuario).

0

Necesita envolver todo como una cadena literal. Estás tratando de imprimir eso como una cadena, supongo, ¿correcto?

0

Respuesta corta: No se puede. El resultado de la evaluación de expresión se pasa a la función en lugar de a la expresión misma.

1

Parece ser que pueda volver tuplas de 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

Puedes devolver todo lo que quieras de '__eq__', pero devolver algo que no se puede forzar a un bool para comparar la igualdad - el propósito de' __eq__' - es una muy mala idea. –

+0

Probablemente sea una mala práctica, pero esta es una pregunta teórica de todos modos. Más de un "¿Cómo es esto posible?" tipo cosa. –

+0

SQLalchemy realmente hace algo como esto? Esa es una biblioteca que no tocaré con un poste de acero de 20 pies. Es un hack asqueroso y repugnante. (No atacarte, solo estás explicando cómo podrían haberlo hecho). –

5

Una variante aún más pitón de la solución de Nelson es usar las funciones del operador del módulo operator en la biblioteca estándar; no hay necesidad de crear sus propias lambdas.

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

Tienes que implementar __eq__(). Por ejemplo ::

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

Entonces, para la función que desea obtener la expresión, como ::

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

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