2008-12-02 5 views
36

Je voudrais être en mesure d'imprimer le code de définition d'une fonction lambda.imprimer le code qui définit une fonction lambda

Exemple si je définir cette fonction par la syntaxe lambda:

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

Je voudrais obtenir cette sortie:

x==2 
+1

Veuillez utiliser 'def x (args)' au lieu de 'x = lambda (args)'. Cela ne répond pas à votre question, mais s'il vous plaît utilisez def pour cela. –

Répondre

54

Tant que vous enregistrez votre code dans un fichier source vous pouvez récupérer le code source de un objet à l'aide du module inspecter.

exemple: type d'éditeur ouvert:

myfunction = lambda x: x==2 

Enregistrer sous lamtest.py

python type shell ouvert pour obtenir le type python interactif comme suit:

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

le résultat :

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

Une idée sur pourquoi il ne peut pas fonctionner dans le shell python? – noamtm

+6

il ne fonctionne pas dans le shell car le code n'est pas défini dans un fichier, inspect examine l'attribut __file__ et ouvre ce fichier et le lit. – Moe

+0

fonctionne dans IPython, agréable –

-1

Pourquoi voulez-vous faire?

Je suppose que vous pouvez utiliser le « dis » module pour démonter votre code pour bytecode python, mais il est probablement pas ce que vous voulez.

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

Encore une fois, je ne vois pas le cas d'utilisation pour cela. Peut-être qu'éval() est plus adapté à votre problème. Il est intégré, et vous pouvez ensuite utiliser des chaînes pour passer le code dans votre code.

+0

J'ai construit une machine d'état. Les conditions pour passer d'un état à un autre sont définies par les fonctions lambda. Je voulais tracer un graphe de cette machine d'état, avec les fonctions lambda au-dessus de chaque arc. – Mapad

+0

Malheureusement, les décompilateurs python sont en mauvais état, il y en a un pour <= 2,5 là-bas. –

+0

Un autre cas d'utilisation serait une forme de documentation automatique améliorée - les Lambda sont parfois utilisées comme valeurs par défaut dans les fonctions/méthodes (par exemple les tris etc.). Il serait utile pour un documenteur automatisé de pouvoir lister le code source lamda lors de la documentation de la signature de fonction/méthode. –

6

Cela sera très difficile, car votre fonction lambda sera compilée en bytecode, et votre objet myfunction pointera uniquement vers le bytecode et non le code lisible par l'utilisateur que vous avez écrit.

Par exemple, si vous définissez 2 fonctions, l'une en utilisant la syntaxe lambda et un à l'aide d'une instruction def, comme suit:

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

Ces 2 objets (lambda_func et def_func) seront équivalentes pour autant que python est concerné. En fait, si vous allez de l'avant et de les démonter en utilisant les dis module (comme ondulature suggéré), vous obtiendrez des résultats identiques:

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

Cela étant le cas, vous pouvez voir comment il serait difficile d'obtenir le code d'origine quand il est un beaucoup à une relation

1

Comment agit-il?

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

Par rapport à la solution de pcn, cela fonctionne dans la console, même si vous avez supprimé le code source. Le seul inconvénient de ceci est que vous devez mettre le code dans une chaîne ... – Mapad

+0

@Mapad: Pas un inconvénient. La seule façon de satisfaire votre exigence sans modifier le compilateur Python pour enregistrer la source dans une docstring. –

18

Il ne fonctionne que pour les opérations basées mathématiques, mais vous pouvez regarder SymPy « objet de Lambda().Il a été conçu exactement à cet effet:

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

Il supporte même assez l'impression:

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

Pour faire votre égal exemple, nous l'objet sympy équation():

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

Il prend en charge l'extension des arguments partiels:

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

Et bien sûr, vous obtenez l'avantage d'obtenir toutes l'algèbre informatique sympy:

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

Par ailleurs, si cela ressemble à un bouchon sans vergogne, c'est parce qu'il est. Je suis l'un des développeurs de SymPy.

+0

sympy est une pièce étonnante de logiciel, sans vergogne pour ne pas l'utiliser! Merci beaucoup :) –

8

Bien que je sois généralement d'accord que inspect est une bonne réponse, je ne serais pas d'accord que vous ne pouvez pas obtenir le code source des objets définis dans l'interpréteur. Si vous utilisez dill.source.getsource de dill, vous pouvez obtenir la source des fonctions et lambdas, même si elles sont définies de manière interactive. Il peut également obtenir le code pour les méthodes et fonctions de classes liées ou non liées définies dans les currys ... cependant, vous ne pourrez peut-être pas compiler ce code sans le code de l'objet englobant.

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

>>> 
Questions connexes