Supposons que j'ai une fonction Python telle que définie ci-dessous:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
Je peux obtenir le nom de la fonction en utilisant foo.func_name
. Comment puis-je obtenir par programme son code source, comme je l'ai tapé ci-dessus?
foo.__name__
Réponses:
Si la fonction provient d'un fichier source disponible sur le système de fichiers, cela
inspect.getsource(foo)
peut être utile:Si
foo
est défini comme:Alors:
Retour:
Mais je crois que si la fonction est compilée à partir d'une chaîne, d'un flux ou importée à partir d'un fichier compilé, vous ne pouvez pas récupérer son code source.
la source
len
. Où puis-je trouver le code source de lalen
fonction?inspect.getsourcelines(foo)
Le module d'inspection dispose de méthodes pour récupérer le code source à partir d'objets python. Apparemment, cela ne fonctionne que si la source se trouve dans un fichier. Si vous l'aviez, je suppose que vous n'auriez pas besoin d'obtenir la source de l'objet.
la source
python 3.5.3
interprète.import inspect
+inspect.getsource(foo)
a bien fonctionné.dis
est votre ami si le code source n'est pas disponible:la source
Si vous utilisez IPython, vous devez taper "foo ??"
la source
dir(MyClass)
puisMyClass.__init__??
et ainsi de suite.Bien que je convienne généralement que
inspect
c'est une bonne réponse, je ne suis pas d'accord pour dire que vous ne pouvez pas obtenir le code source des objets définis dans l'interpréteur. Si vous utilisezdill.source.getsource
fromdill
, vous pouvez obtenir la source des fonctions et des lambdas, même s'ils sont définis de manière interactive. Il peut également obtenir le code des méthodes et fonctions de classe liées ou non définies définies dans les currys ... cependant, vous ne pourrez peut-être pas compiler ce code sans le code de l'objet englobant.la source
dill.source.getsource
inspecte l'historique de l'interpréteur pour les fonctions, classes, lambdas, etc. - il n'inspecte pas le contenu des chaînes passées à exec.dill
pour répondre à cette question: stackoverflow.com/questions/13827543/…dill.source
a des fonctions commegetname
etimportable
etgetsource
qui se concentrent sur l'obtention du code source (ou d'un importable qui donne l'objet) pour tout objet donné. Pour des choses simples comme anint
il n'y a pas de source, donc cela ne fonctionne pas comme prévu (c'est-à-dire que pour 'a = 10' il retourne '10').>>> a = 10; print( [key for key, val in globals().items() if val is a][0] )
dill
, mais ma réponse laisse un peu à désirer (IE, si vous avez plusieurs noms pour la même valeur, il ne peut pas déterminer lequel a été utilisé. Si vous passer une expression, il ne peut pas dire ce que cette expression était. Heck, si vous passez une expression qui équivaut à un nom, il donnera ce nom à la place.) Peutdill
résoudre l'un de ces défauts de ma réponse ici: stackoverflow.com/a/28634996/901641Pour développer la réponse de runeh:
EDIT: Comme indiqué par @ 0sh, cet exemple fonctionne en utilisant
ipython
mais pas en clairpython
. Cependant, cela devrait convenir dans les deux cas lors de l'importation de code à partir de fichiers source.la source
getsource(foo)
.Vous pouvez utiliser le
inspect
module pour obtenir le code source complet pour cela. Vous devez utiliser lagetsource()
méthode pour cela à partir duinspect
module. Par exemple:Vous pouvez le vérifier plus d'options sur le lien ci-dessous. récupérer votre code python
la source
Étant donné que ce message est marqué comme le double de cet autre message , je réponds ici pour le cas "lambda", bien que l'OP ne concerne pas les lambdas.
Donc, pour les fonctions lambda qui ne sont pas définies dans leurs propres lignes: en plus de la réponse de marko.ristin , vous pouvez utiliser mini-lambda ou utiliser SymPy comme suggéré dans cette réponse .
mini-lambda
est plus léger et prend en charge tout type d'opération, mais ne fonctionne que pour une seule variableSymPy
est plus lourd mais beaucoup plus équipé d'opérations mathématiques / calcul. En particulier, cela peut simplifier vos expressions. Il prend également en charge plusieurs variables dans la même expression.Voici comment vous pouvez le faire en utilisant
mini-lambda
:Il donne correctement
Voir la
mini-lambda
documentation pour plus de détails. Je suis l'auteur d'ailleurs;)la source
Veuillez noter que les réponses acceptées ne fonctionnent que si le lambda est indiqué sur une ligne distincte. Si vous le transmettez en tant qu'argument à une fonction et que vous souhaitez récupérer le code du lambda en tant qu'objet, le problème devient un peu délicat car
inspect
il vous donnera la ligne entière.Par exemple, considérons un fichier
test.py
:L'exécuter vous donne (attention à l'indentation!):
Pour récupérer le code source du lambda, mon meilleur pari, à mon avis, est de ré-analyser le fichier source entier (en utilisant
f.__code__.co_filename
) et de faire correspondre le nœud lambda AST par le numéro de ligne et son contexte.Nous avons dû faire précisément dans notre bibliothèque de conception par contrat IContract puisque nous devions analyser les fonctions lambda , on passe comme arguments aux décorateurs. C'est trop de code à coller ici, alors jetez un œil à l'implémentation de cette fonction .
la source
Si vous définissez strictement la fonction vous-même et que sa définition est relativement courte, une solution sans dépendances serait de définir la fonction dans une chaîne et d'assigner l'eval () de l'expression à votre fonction.
Par exemple
puis éventuellement attacher le code d'origine à la fonction:
la source
résumer :
la source
Je crois que les noms de variables ne sont pas stockés dans des fichiers pyc / pyd / pyo, vous ne pouvez donc pas récupérer les lignes de code exactes si vous n'avez pas de fichiers source.
la source