gratifiant > comp.lang.* > comp.lang.python

Fabrice (01/09/2019, 21h29)
Bonjour,

imaginons que j'ai écrit une fonction dans la console.

def f(x):
if x<0: return -1
else : return 1

je suis toujours dans la console.
Existe-t-il le moyen d'afficher la définition de la fonction f ?

Du genre, je tape

>>> AFFICHE_DEF(f)


et je vois apparaître

def f(x):
if x<0: return -1
else : return 1

Je pense à cette idée puisque Python est interprété donc on a forcément
accès au code source...

Merci,
Fabrice.
yves (02/09/2019, 10h38)
Le Sun, 01 Sep 2019 21:29:18 +0200, Fabrice a écrit:

Bonjour,

> je suis toujours dans la console.
> Existe-t-il le moyen d'afficher la définition de la fonction f ?


Pas vraiment possible d'après cette discussion:


in-interactive-shell

sauf ce hack sous linux:

import readline
readline.write_history_file('/tmp/hist.txt')

et lire hist.txt

Ceci dit, si tu penses vraiment avoir besoin de faire ça (si ce n'est pas
juste une question théorique), ça signifie, à mon avis et sauf
démonstration du contraire, que ta façon de travailler n'est pas optimale.

@+
Fabrice (03/09/2019, 09h01)
Le 02/09/2019 à 10:38, yves a écrit :
> ta façon de travailler n'est pas optimale.


Je ne cherche pas à travailler mais à enseigner ;-)

et parfois, mes élèves s'emmêlent les pinceaux et croient utiliser une
fonction alors que c'en est une autre... surtout avec jupyter qui permet
de réexécuter les cadres de code passés.

Du coup, lorsqu'ils m'appellent au secours, ils ont parfois un
"programme" qui semblent bon mais qui ne marche pas car l'erreur est
dans une fonction qu'ils appellent et qui n'est pas celle qu'ils croient.

Et quand ils me disent : "Mais si m'sieur, j'ai bien écrit ma fonction"
en me montrant le cadre de code qu'ils ont changé mais pas exécuté,
j'aimerai leur montrer ce que Python connait vraiment.

Cordialement,
Fabrice.
Becaree (03/09/2019, 20h56)
La réponse la plus simple que je pourrais vous donner est . Donc pas de globals beaucoup moins de soucis et sinon le code doit etre écrit quelque part, il y a des moyen d'accéder aux noms du module auxquel appartient une fonction avec:
import sys
getattr(sys.modules[__name__], 'f')
Cependant vous ne verrez la fonction qui est disponible dans les globaux seulement
C'est à dire si vous avez appeler une variable math, le module pass à l'oubliette. Quand au fait python est interprété, oui, et cela veut dire qu'a un moment dans l'interpreteur y'a eu des méthodes avec exec, eval et compile dont on pourrait très bien "affiché lecorps" mais vous allez pas faire coder vos élèves ainsi
Benoit Izac (03/09/2019, 21h28)
Bonjour,

Le 03/09/2019 à 09:01, Fabrice a écrit dans le message
<5d6e0fbd$0$3528$426a74cc> :

> et parfois, mes élèves s'emmêlent les pinceaux et croient utiliser une
> fonction alors que c'en est une autre... surtout avec jupyter qui
> permet de réexécuter les cadres de code passés.
> Du coup, lorsqu'ils m'appellent au secours, ils ont parfois un
> "programme" qui semblent bon mais qui ne marche pas car l'erreur est
> dans une fonction qu'ils appellent et qui n'est pas celle qu'ils
> croient.
> Et quand ils me disent : "Mais si m'sieur, j'ai bien écrit ma
> fonction" en me montrant le cadre de code qu'ils ont changé mais pas
> exécuté, j'aimerai leur montrer ce que Python connait vraiment.


Le problème c'est que, bien que Python soit interprété, il exécute du
bytecode. Donc le seul moyen est de désassembler le bytecode mais c'est
plus compliqué à lire car tu obtiens un genre d'assembleur. Sur ta
fonction « f » :

>>> def f(x):

.... if x<0: return -1
.... else : return 1
....
>>> import dis
>>> dis.dis(f)

2 0 LOAD_FAST 0 (x)
2 LOAD_CONST 1 (0)
4 COMPARE_OP 0 (<)
6 POP_JUMP_IF_FALSE 12
8 LOAD_CONST 2 (-1)
10 RETURN_VALUE

3 >> 12 LOAD_CONST 3 (1)
14 RETURN_VALUE
16 LOAD_CONST 0 (None)
18 RETURN_VALUE

Voir <https://docs.python.org/3/library/dis.html> pour plus de détail.
Nicolas (06/09/2019, 08h43)
Bonjour,

> et parfois, mes élèves s'emmêlent les pinceaux et croient utiliser une
> fonction alors que c'en est une autre... surtout avec jupyter qui permet
> de réexécuter les cadres de code passés.
> Du coup, lorsqu'ils m'appellent au secours, ils ont parfois un
> "programme" qui semblent bon mais qui ne marche pas car l'erreur est
> dans une fonction qu'ils appellent et qui n'est pas celle qu'ils croient.
> Et quand ils me disent : "Mais si m'sieur, j'ai bien écrit ma fonction"
> en me montrant le cadre de code qu'ils ont changé mais pas exécuté,
> j'aimerai leur montrer ce que Python connait vraiment.


D'après cette réponse
(),
il semblerait que les lignes suivantes fonctionnent dans jupyter :

import inspect
print(inspect.getsource(fonction))

A vérifier...
Je n'utilise pas jupyter, donc, je ne peux pas vérifier ;)

Nicolas
Benoit Izac (06/09/2019, 19h25)
Bonjour,

Le 06/09/2019 à 08:43, Nicolas a écrit dans le message
<5d71fffd$0$15180$426a74cc> :

> D'après cette réponse
> (),
> il semblerait que les lignes suivantes fonctionnent dans jupyter :
> import inspect
> print(inspect.getsource(fonction))
> A vérifier...
> Je n'utilise pas jupyter, donc, je ne peux pas vérifier ;)


Ce n'est pas spécifique à Jupyter et tu as lu un peu vite :

| If the function is from a source file available on the filesystem,
| [...]
| But I believe that if the function is compiled from a string, stream
| or imported from a compiled file, then you cannot retrieve its source
| code.

Lorsque le code est tapé dans la console, le fichier source n'est pas
disponible donc ça ne fonctionne pas. Ça ne marche que ce que tu vas
trouver dans /usr/lib/pythonX.X/.
Fabrice (07/09/2019, 18h56)
Bonjour,

j'utilise Anaconda à la maison et dans la console de spyder, la méthode
proposé par Nicolas fonctionne très bien.

Elle fonctionne aussi dans Jupyter.

Merci Nicolas.

cordialement,
Fabrice.
Nicolas (09/09/2019, 08h32)
Le 06/09/2019 à 19:25, Benoit Izac a écrit :
[..]
>> Je n'utilise pas jupyter, donc, je ne peux pas vérifier ;)

> Ce n'est pas spécifique à Jupyter et tu as lu un peu vite : Non non, je n'ai pas lu trop vite :1806a74cc> :
> Ce n'est pas spécifique à Jupyter et tu as lu un peu vite : Non non, je n'ai pas lu trop vite :


"to my surprise, it works in Ipython/Jupyter notebooks also ? Dr. Goulu
Jan 22 '16 at 11:51"

;)
Nicolas (09/09/2019, 08h32)
Le 07/09/2019 à 18:56, Fabrice a écrit :
[..]
Benoit Izac (09/09/2019, 19h06)
Bonjour,

Le 09/09/2019 à 08:32, Nicolas a écrit dans le message
<5d75f1f4$0$6460$426a74cc> :

> Non non, je n'ai pas lu trop vite :
> "to my surprise, it works in Ipython/Jupyter notebooks also ? Dr.
> Goulu Jan 22 '16 at 11:51"


C'est plutôt moi qui n'ai pas tout lu. ;-)

Et c'est parce qu'il garde une trace du code source (dans
~/.ipython/profile_default/history.sqlite chez moi). D'un autre coté, il
suffit d'utiliser la flèche du haut pour voir ce qui a été exécuté en
dernier.
Discussions similaires