71

I'd like to be able to print the definition code of a lambda function.

Example if I define this function through the lambda syntax:

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

I'd like to get this output:

x==2
3
  • 2
    Please use def x( args ) instead of x= lambda( args ). This doesn't answer your question, but please use def's for this. Commented Dec 2, 2008 at 18:00
  • 2
    Since this post is marked as duplicate it is not possible to post answers anymore. However the duplicate post concerns plain functions, not lambdas. I posted an answer specific to lambdas here: stackoverflow.com/a/55760092/7262247 Commented Apr 19, 2019 at 10:05
  • I found it easier to capture the desired function as a string, then evaluate it in my lambda function e.g.where f is a string defining the function: map(lambda x: eval(f), x). In this way the function is defined once but still available as text. Commented Nov 2, 2019 at 22:32

6 Answers 6

98

As long as you save your code to a source file you can retrieve the source code of an object using the inspect module.

example: open editor type:

myfunction = lambda x: x==2

save as lamtest.py

open shell type python to get to interactive python type the following:

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

the result:

'myfunc = lambda x: x==2\n'
Sign up to request clarification or add additional context in comments.

7 Comments

Any idea on why it cannot work in the python shell?
it doesn't work in the shell because the code is not defined in a file, inspect looks at the file attribute and opens that file and reads it.
works in IPython, nice
@MartinVilcans Yeah! You can even fly: terminal --> python [enter] import antigravity :) Seriously
This doesn't exactly answer the question. Is there a way to get just x==2 instead of the full source code surrounding the declaration?
|
27

It will only work for mathematical based operations, but you might look at SymPy's Lambda() object. It was designed exactly for this purpose:

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

It even supports pretty printing:

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

To do your equals example, us the SymPy Eq() object:

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

It supports partial argument expansion:

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

And of course, you get the advantage of getting all of SymPy's computer algebra:

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

By the way, if this sounds like a shameless plug, it's because it is. I am one of the developers of SymPy.

2 Comments

sympy is an amazing piece of sofware, shameless not to use it! thank you very much :)
Note that if the function is not necessarily mathematics-oriented or is simple, mini_lambda offers a light mono-variable alternative to SymPy: stackoverflow.com/a/55760092/7262247
22

While I'd generally agree that inspect is a good answer, I'd disagree that you can't get the source code of objects defined in the interpreter. If you use dill.source.getsource from dill, you can get the source of functions and lambdas, even if they are defined interactively. It also can get the code for from bound or unbound class methods and functions defined in curries... however, you might not be able to compile that code without the enclosing object's code.

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

>>> 

1 Comment

This module doesn't seem to work with Jupyter notebooks, FYI - see here.
10

That will be very difficult, because your lambda function will be compiled to bytecode, and your myfunction object will only be pointing to the bytecode and not the human-readable code that you wrote.

For example, if you define 2 functions, one using lambda syntax and one using a def statement, as follows:

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

These 2 objects (lambda_func and def_func) will be equivalent as far as python is concerned. In fact, if you go ahead and disassemble them using the dis module (as rebra suggested), you will get identical results:

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

That being the case, you can see how it would be difficult to obtain the original code when it's a many to one relationship

Comments

0

How's this?

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

2 Comments

Compared to the solution from pcn, this works in the console, even if you've deleted the source code. The only downside of this is that you need to put the code in a string...
@Mapad: Not a downside. The only way to satisfy your requirement without modding the Python compiler to save source in a docstring.
-8

Why do you want to do this?

I guess you could use the "dis" module to disassemble your code to python bytecode, but it's probably not what you want.

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

Again, I can't see the use case for this. Perhaps eval() is more suited for your problem. It is built in, and then you can use strings to pass code around in your code.

4 Comments

I've built a state machine. The conditions to go from one state to another are defined by lambda functions. I wanted to plot a graph of this state machine, with the lambda functions on top of each arc.
Sadly python decompilers are in rather poor state, there's one for <=2.5 out there.
Another use case would be a form of enhanced automatic documentation - Lambda's are sometimes used as default values in functions/methods (for instance sorts etc). It would be useful for an automated documentor to be able to list the lamda source code when documenting the function/method signature.
Down voted this answer because, I personally feel an answer should not start with "Why do you want to do this?".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.