2008-12-02 11 views
36

Me gustaría poder imprimir el código de definición de una función lambda.imprime el código que define una función lambda

Ejemplo si definir esta función a través de la sintaxis lambda:

>>>myfunction = lambda x: x==2 
>>>print_code(myfunction) 

me gustaría conseguir este resultado:

x==2 
+1

Por favor, use 'def x (args)' en lugar de 'x = lambda (args)'. Esto no responde su pregunta, pero use def para esto. –

Respuesta

54

Mientras se guarda el código en un archivo fuente se puede recuperar el código fuente de un objeto utilizando el módulo de inspeccionar.

ejemplo: abierta editor tipo:

myfunction = lambda x: x==2 

guardar como lamtest.py

concha abierta tipo pitón llegar a interactiva tipo pitón lo siguiente:

>>>from lamtest import myfunc 
>>>import inspect 
>>>inspect.getsource(myfunc) 

el resultado :

'myfunc = lambda x: x==2\n' 
+4

¿Alguna idea sobre por qué no puede funcionar en el shell de python? – noamtm

+6

no funciona en el shell porque el código no está definido en un archivo, inspecciona busca en el atributo __file__ y abre ese archivo y lo lee. – Moe

+0

funciona en IPython, agradable –

-1

¿Por qué quieres hacer esto?

Supongo que podría usar el módulo "dis" para desmontar su código a bytecode de python, pero probablemente no es lo que quiere.

http://www.python.org/doc/2.5.2/lib/module-dis.html

Una vez más, no puedo ver el caso de uso para esto. Tal vez eval() es más adecuado para su problema. Está integrado, y luego puede usar cadenas para pasar el código en su código.

+0

He creado una máquina de estados. Las condiciones para ir de un estado a otro están definidas por las funciones lambda. Quería trazar un gráfico de esta máquina de estado, con las funciones lambda en la parte superior de cada arco. – Mapad

+0

Tristemente los descompiladores de Python están en un estado bastante pobre, hay uno para <= 2.5. –

+0

Otro caso de uso sería una forma de documentación automática mejorada: los Lambda a veces se usan como valores predeterminados en funciones/métodos (por ejemplo, ordenaciones, etc.). Sería útil para un documento automatizado o para poder listar el código fuente de lamda al documentar la firma de la función/método. –

6

que será muy difícil, debido a que su función lambda será compilado a código de bytes, y su objeto mifuncion sólo se apunta al código de bytes y no el código legible por humanos que escribiste.

Por ejemplo, si se define 2 funciones, una usando la sintaxis lambda y el otro con una declaración def, de la siguiente manera:

>>> lambda_func = lambda x: x==2 
>>> def def_func(x): return x == 2 
... 

Estos 2 objetos (lambda_func y def_func) serán equivalentes por lo que pitón es preocupado. De hecho, si seguir adelante y desmontarlas utilizando los dis module (como rebra sugirió), obtendrá resultados idénticos:

>>> import dis 
>>> dis.dis(lambda_func) 
    1   0 LOAD_FAST    0 (x) 
       3 LOAD_CONST    1 (2) 
       6 COMPARE_OP    2 (==) 
       9 RETURN_VALUE 
>>> dis.dis(def_func) 
    1   0 LOAD_FAST    0 (x) 
       3 LOAD_CONST    1 (2) 
       6 COMPARE_OP    2 (==) 
       9 RETURN_VALUE 

Siendo ese el caso, se puede ver cómo sería difícil obtener el código original cuando se trata de una relación muchos a uno

1

¿Cómo es esto?

class MyLambda(object): 
    def __init__(self, body): 
     self.body= body 
    def __call__(self, arg): 
     x = arg 
     return eval(self.body) 
    def __str__(self): 
     return self.body 

f= MyLambda("x == 2") 
print f(1) 
print f(2) 
print f 
+0

Comparado con la solución de pcn, esto funciona en la consola, incluso si ha eliminado el código fuente. El único inconveniente de esto es que necesita poner el código en una cadena ... – Mapad

+0

@Mapad: No es un inconveniente. La única forma de satisfacer su requerimiento sin modificar el compilador de Python para guardar el origen en una docstring. –

18

Funcionará solo para operaciones basadas en matemática, pero puede consultar el objeto SymPyLambda().Fue diseñado exactamente para este propósito:

>>> from sympy import * 
>>> x = Symbol('x') 
>>> l = Lambda(x, x**2) 
>>> l 
Lambda(_x, _x**2) 
>>> l(3) 
9 

Incluso soporta bastante impresión:

>>> pprint(l) 
⎛ 2⎞ 
Λ⎝x, x ⎠ 

para hacer su igual ejemplo, nosotros el sympy la ecuación() del objeto:

>>> l1 = Lambda(x, Eq(x, 2)) 
>>> l1 
Lambda(_x, _x == 2) 
>>> l1(2) 
True 

se admite la expansión parcial de argumentos:

>>> y = Symbol('y') 
>>> l2 = Lambda((x, y), x*y + x) 
>>> l2(1) 
Lambda(_y, 1 + _y) 
>>> l2(1, 2) 
3 

Y, por supuesto, se obtiene la ventaja de obtener todos álgebra computacional de sympy:

>>> l3 = Lambda(x, sin(x*pi/3)) 
>>> pprint(l3(1)) 
    ⎽⎽⎽ 
╲╱ 3 
───── 
    2 

Por cierto, si esto suena como un enchufe descarado, es porque lo es. Soy uno de los desarrolladores de SymPy.

+0

sympy es una increíble pieza de software, ¡sinvergüenza de no usarla! muchas gracias :) –

8

Aunque generalmente estoy de acuerdo con que inspect es una buena respuesta, no estoy de acuerdo con que no se pueda obtener el código fuente de los objetos definidos en el intérprete. Si usa dill.source.getsource de dill, puede obtener la fuente de funciones y lambdas, incluso si se definen de forma interactiva. También puede obtener el código de métodos y funciones de clase enlazados o no definidos definidos en curries ... sin embargo, es posible que no pueda compilar ese código sin el código del objeto adjunto.

>>> from dill.source import getsource 
>>> 
>>> def add(x,y): 
... return x+y 
... 
>>> squared = lambda x:x**2 
>>> 
>>> print getsource(add) 
def add(x,y): 
    return x+y 

>>> print getsource(squared) 
squared = lambda x:x**2 

>>> 
>>> class Foo(object): 
... def bar(self, x): 
...  return x*x+x 
... 
>>> f = Foo() 
>>> 
>>> print getsource(f.bar) 
def bar(self, x): 
    return x*x+x 

>>> 
Cuestiones relacionadas