Напечатать код, который определил лямбда-функцию
Я хотел бы иметь возможность распечатать код определения лямбда-функции.
Пример, если я определю эту функцию через лямбда-синтаксис:
>>>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() больше подходит для вашей проблемы. Он встроен, и тогда вы можете использовать строки для передачи кода в вашем коде.