Substituer dans un programme python

Bonjour
Parfois j'écris un programme en python par exemple
def A(x,y,..)  :
   blabla a(x) blabla
   blabla 
   blabla a(x) blabla 
   blabla....
Avec parfois trop d' occurrence de a(x) pour que ça puisse m'ennuyer de remplacer à la main a(x) par disons b(x)

QUESTION 1
Y a-t-il un moyen de le faire directement du style :
Def B(x,y,etc...)= FonctionDeSubstitution(A(x,y,..), a=b)
Certes "FonctionDeSubstitution" porte sur des programme, qui (à ma très basique connaissance) ne sont pas des types python mais est-ce insurmontable ?

Par exemple s'il existe une fonction appelons la F, qui lorsqu'on lui donne le nom d'un programme nous donne le programme*** lui même et qu'on a G sa réciproque, alors je peux moi-même sans difficulté fabriquer ce que je veux (il faudrait aussi que je sache comment on fait "remplacer par"*** mais c'est un détail...)

QUESTION 2
Si ça n'est pas possible, dans quel langage (de référence orienté objet) l'est-ce ?
Merci d'avance !

***l'indentation peut être un problème... du coup il faudrait une fonction qui transforme une seule ligne en programme indenté et ensuite jongler avec la fonction qui transforme cette ligne en texte et les fonction classique de remplacement "texte to texte" (dont le nom m'échappe ...)

Réponses

  • J'avoue ne pas avoir bien compris ta demande... $a$ et $b$ sont des fonctions ?

    Ce qui est possible en Python est de mettre des fonctions comme argument d'autres fonctions. Par exemple
    def composee(f,x):
        return f(f(x))
    
    peut s'utiliser avec n'importe quelle fonction $f$.

    Donc dans ton exemple, tu peux très bien mettre
    def A(x,y,f):
        blabla f(x) blabla
        blabla
        blabla f(x) blabla
        blabla
    
    puis pour l'utiliser avec $a$ puis $b$:
    A(x,y,a)
    A(x,y,b)
    
  • Bonjour
    S'il s'agit de remplacer du texte, n'importe quel éditeur de texte a une fonction de remplacement portant sur toutes les occurrences.
    Un éditeur comme emacs permet de définir des macros localement (faisant ce que tu veux, par exemple des recherches puis remplacements) et de les utiliser immédiatement.
    Alain
  • En Python, il y a la fonction eval() qui ressemble un peu à ton besoin.
    Sinon, le mot clé pour faire des recherches, je pense que c'est indirect ou indirection.
    Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. Benjamin Franklin
  • Merci pour vos réponses, et merci à AD aussi pour les éditions.

    @ lourran, ton premier post ne réponds pas exactement à ma question mais il me rend bien service (je trouvais ça bizarre qu'on ne puisse pas faire avec les fonction comme on fait avec les constantes, et ça ne fonctionnait pas quand j'écrivais
    A(x,y,f=a)
    

    au lieu de
    A(x,y,a)
    

    Le problème qu'est le miens est un peu différent, grâce à toi, je peu, en ayant prévu à l'avance de changer de fonction, le faire effectivement. Mais quand je me rends compte a posteriori que je préférerais $b$ à $a$, il faut de toute façon revenir dans le code et changer manuellement $a$ en $b$.

    Sauf si une fonction me permet de le faire.
    @AD : une fonction de texte dans texte n'est pas le problème (même si je ne connais pas son nom dans python)
    Il faut en fait une fonction qui prenne en entrée le programme indenté et sorte un programme indenté avec le changement, il y a donc un problème de type (que résout "eval") mais un programme indenté est-il un type? je ne crois pas, enfin pas sûr...


    Du coup, l’idéal serait deux fonctions réciproques l'une de l'autres disons Indent et IndentRcp telle que IndentRcp transforme tout $F$ tel que
    def F(x,y,z) :
    blabla
    

    en une ligne texte (ou autre type que texte mais ça "eval" résout le problème).

    Du coup, en appelant SUB la fonction qui substitue $b$ à $a$ dans le texte on aurait qu'à faire
    Indent((SUB(b,a)(IndentRcp(F)))
    


    Je ne sais pas si c'est plus clair...


    @lourran je viens de voir ton post avec le mot clé, je vais regarder tout de suite...

    Merci encore^^
  • Tu peux utiliser getsource du module inspect, la méthode replace pour modifier la chaîne et la fonction exec (plutôt qu'eval).
  • @ Philippe Malot : Merci<3
  • Voilà un bout de code !
    from inspect import getsource
    
    def f(x):
        print('a(x) = %d < 10' % a(x) if a(x) < 10 else 'Plop!')
        
    def a(x):
        return x ** 2
    
    def b(x):
        return x ** 3
    
    s = getsource(f).replace('a(x)','b(x)')
    f(3)
    exec(s)
    f(3)
    f(2)
    
  • Ça a l'air rigolo de jouer avec le code source en live comme ça, mais question propreté, je préfère mille fois la solution de Héhéhé . Une fonction en Python est un objet comme les autres, elle peut donc être passée en argument à d'autres fonctions. Par ailleurs, lorsque f est une fonction, on peut faire des choses comme f(*args, **kwargs) qui peuvent être bien pratiques.
  • Merci pour cet exemple Philippe Malot, subtil, car il illustre aussi le cas des guillemets dans le programme même!
  • Je ne vois toujours pas l'intérêt par rapport à utiliser des arguments qui sont eux-mêmes des fonctions.

    C'est une idée catastrophique du point de vue de la programmation que de changer le texte du programme d'une fonction en live. Je te déconseille absolument de faire cela.
  • merci brian et Héhéhé, je vais suivre votre conseil...en fait c'est toujours instructif de savoir ce qu'on peut faire, même si on devrait ne pas le faire et qu'on devrait ne pas le faire.
  • Oui tu as raison.
  • Héhéhé a écrit:
    C'est une idée catastrophique du point de vue de la programmation que de changer le texte du programme d'une fonction en live. Je te déconseille absolument de faire cela.

    Philippe Malot ne change pas le code source en live, il crée une nouvelle fonction dont le code source est inspiré d’une autre.
    Je ne vois pas pourquoi ça serait par principe interdit (c’est risqué, on est d’accord et probablement interdit dans un tas de cahiers des charges).
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • En fait, moi, je ne vois pas l'intérêt de faire ce que veut faire @lesmathspointsclaires.
    • Soit c'est un problème d'éditeur de texte... et tout bon éditeur possède une fonction "rechercher/remplacer" qui répondra à la question.
    • Soit c'est un problème de factorisation de code pour le condenser... auquel cas, la solution de HéHéHé me paraît parfaite.
    • Soit c'est un problème de conception du programme : on veut modifier une partie du code qui se répète à tous les endroits où il se répète. Eh bien, il aurait fallu créer une fonction à la place de cette partie qui se répète et la seule modification de la fonction aurait permis de régler le problème.
    Je penche pour la 3ème solution, pour le problème de @lesmathspointsclaires.
  • nicolas.patrois a écrit:
    Philippe Malot ne change pas le code source en live, il crée une nouvelle fonction dont le code source est inspiré d’une autre.

    Hum, as-tu lu le code ? L'instruction exec(s) modifie bel et bien la fonction f en live. D'ailleurs, si tu l'avais testé, tu aurais bien vu que les deux f(3) dans :
    f(3)
    exec(s)
    f(3)
    
    n'affichent pas la même chose. De plus, même si ça faisait ce que tu crois, utiliser cette technique serait une mauvaise idée à mon avis, car le vrai problème, c'est que le remplacement de code effectué de cette manière est bête et méchant, il ignore tout de la structure du langage. En particulier, comme le prouve l'exemple suivant, la fameuse séquence :
    s = getsource(f).replace('a(x)', 'b(x)')
    exec(s)
    
    remplace joyeusement ca(x) par cb(x) ou même whatevera(x) par whateverb(x). C'est donc très risqué.
    from inspect import getsource
    
    def f(x):
        print((a(x), ca(x)))
    
    def a(x):
        return x ** 2
    
    def b(x):
        return x ** 3
    
    def ca(x):
        return -x
    
    def cb(x):
        return -10*x
    
    s = getsource(f).replace('a(x)', 'b(x)')
    f(3)
    exec(s)
    f(3)
    
    Ce programme affiche :
    (9, -3)
    (27, -30)
    
    Malgré l'apparence anodine de getsource(f).replace('a(x)', 'b(x)'), ceci a silencieusement remplacé l'appel à la fonction ca dans la définition de f par un appel à une autre fonction, cb — laquelle pourrait d'ailleurs ne pas avoir été définie, on aurait alors droit à une petite levée d'exception.
    nicolas.patrois a écrit:
    Je ne vois pas pourquoi ça serait par principe interdit (c’est risqué, on est d’accord et probablement interdit dans un tas de cahiers des charges).

    Cela n'est pas interdit par la constitution, en effet... pas plus que de se jeter du haut d'une falaise. À chacun de juger si c'est vraiment une bonne chose à faire, au cas par cas...

    (De toute façon, la question est vraiment mal posée. Sans un bout de code concret, on nage dans le flou le plus complet.)
Connectez-vous ou Inscrivez-vous pour répondre.