Напечатать код, который определил лямбда-функцию

Я хотел бы иметь возможность распечатать код определения лямбда-функции.

Пример, если я определю эту функцию через лямбда-синтаксис:

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

Я хотел бы получить этот вывод:

x==2

6 ответов

Решение

Пока вы сохраняете свой код в исходном файле, вы можете получить исходный код объекта с помощью модуля inspect.

пример: открыть тип редактора:

myfunction = lambda x: x==2

сохранить как lamtest.py

Откройте оболочку типа Python, чтобы перейти к интерактивному типу Python:

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

результат:

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

Это будет работать только для математических операций, но вы можете посмотреть на SymPyLambda() объект. Он был разработан именно для этой цели:

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

Он даже поддерживает красивую печать:

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

Чтобы сделать ваш пример равных, используйте объект SymPy Eq():

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

Он поддерживает частичное расширение аргумента:

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

И, конечно же, вы получаете преимущество получения всей компьютерной алгебры SymPy:

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

Кстати, если это звучит как бесстыдная вилка, это потому, что это так. Я один из разработчиков SymPy.

Хотя я бы вообще согласился, что inspect хороший ответ, я бы не согласился с тем, что вы не можете получить исходный код объектов, определенных в интерпретаторе. Если вы используете dill.source.getsource от dill Вы можете получить источник функций и лямбд, даже если они определены в интерактивном режиме. Он также может получить код для связанных или несвязанных методов и функций класса, определенных в карри... однако вы не сможете скомпилировать этот код без кода вмещающего объекта.

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

>>> 

Это будет очень сложно, потому что ваша лямбда-функция будет скомпилирована в байт-код, а ваш объект myfunction будет указывать только на байт-код, а не на читаемый человеком код, который вы написали.

Например, если вы определили 2 функции, одну из которых использует лямбда-синтаксис, а другую - инструкцию def, выполните следующие действия:

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

Эти 2 объекта (lambda_func и def_func) будут эквивалентны для Python. На самом деле, если вы пойдете и разберете их с помощью модуля dis (как предложил ребра), вы получите идентичные результаты:

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

В таком случае, вы можете увидеть, как будет трудно получить исходный код, когда отношение много к одному.

Как это?

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

Почему ты хочешь сделать это?

Я думаю, вы могли бы использовать модуль "dis", чтобы разобрать ваш код в байт-код Python, но это, вероятно, не то, что вы хотите.

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

Опять же, я не вижу варианта использования для этого. Возможно, eval() больше подходит для вашей проблемы. Он встроен, и тогда вы можете использовать строки для передачи кода в вашем коде.

Другие вопросы по тегам