2016-11-02 1 views
0

Travailler sur mon Python ces jours-ci, et je veux porter un court code Matlab d'un cours que j'ai fait quelques années en Python, mais pour être honnête, je ne peux pas comprendre si c'est possible de le faire de la même manière, et si c'est le cas, comment le faire.Fonctions imbriquées/fonctions anonymes en Python

L'essentiel ici que je me bats avec en Python est le suivant:

nk = @(x)1 
for l=1:3 % calculate basis 
    nk = @(x)(nk(x).*(x-1)); 
end 

Comment le code fonctionne dans Matlab:

nk = @(x)1 crée une fonction poignée nk(x), qui peut être appelé par nk(xi) où, par exemple xi=[1,2,3,4], mais à partir de maintenant, il ne retournera 1 car il ne dépend pas de la variable x, pour le moment.

Dans la boucle for, nk(x) est multiplié par (x-1) pour chaque itération (ici x est considéré comme une variable « symbolique », ou comment l'appeler, semblable à la façon dont vous définissez une fonction lambda), et à la fin il devrait s'avérer comme nk = (x-1)*(x-1)*(x-1).

C'est toujours une fonction que je peux appeler nk(x), où x est un tableau avec toutes les valeurs que je veux qu'il ait.

+0

Même si vous avez donné l'exemple, je ne comprends pas le comportement souhaité de la fonction. Pouvez-vous être un peu plus précis, comme je l'aime beaucoup d'autres ne sauront pas matlab –

+0

Bien sûr. Pour un aperçu général des fonctions anonymes dans Matlab, vous pouvez consulter https://se.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html#f4-70285. Pour le code que j'ai collé, le but est d'obtenir un polynôme d'interpolation comme un handle de fonction afin qu'il puisse être évalué sur différents intervalles sans faire tout le calcul pour chaque ensemble de données. Dire que je veux interpoler certaines données pour lesquelles je connais P (x) = 0.25 * (x-3)^2 + 0.31 * (x-7.21)^3, le code ci-dessus me donne exactement ce P (x) donc j'évalue comme (x, P (x)) (similaire à numpy.polyval). Normalement je ne connais pas ce P (x) a priori. – ritualmagick

+0

Travailler sur votre Python ... Qu'avez-vous essayé jusqu'à présent? Quels sont les problèmes? – chapelo

Répondre

0

L'exemple suivant brut d'interpolation linéaire par morceaux peut vous donner une idée:

def interpolate(xs,ys): 
    #assumes that xs and ys are same-length lists 
    #of real numbers, with xs sorted 
    def N(x): 
     if x < min(xs) or x > max(xs): return False #we don't extrapolate 
     if x == max(xs): return ys[-1] 
     i = 0 
     while xs[i] <= x: 
      i+= 1 
     m = (ys[i]-ys[i-1])/(xs[i]-xs[i-1]) 
     return ys[i-1] + m*(x - xs[i-1]) 
    return N 

Par exemple,

>>> f = interpolate([0,1,2],[1,2,4]) 
>>> f(0) 
1.0 
>>> f(0.7) 
1.7 
>>> f(1.9) 
3.8 
>>> f(2) 
4 
>>> f(2.1) 
False 

Le concept clé est celui de fermetures. Voir this blog pour une discussion agréable (surtout la partie qui parle des usines de fonction).

Par ailleurs, vous pouvez créer des fermetures avec des fonctions anonymes, bien que le code résultant est pas très lisible:

>>> f = (lambda x: (lambda y: x+y)) 
>>> g = f(3) 
>>> g(2) 
5 

Puisque vous mentionniez la fonction « poignées », je ne pense pas que vous avez vraiment veulent des fonctions anonymes (surtout compte tenu de votre question initiale qui avait plus de code Matlab).

+0

Merci pour la réponse détaillée. Un peu plus clair maintenant, mais je dois évidemment creuser plus dans les fonctions internes. Si je comprends bien, la fonction interne a accès à toutes les variables qui sont définies dans la fonction "externe", même si les variables ne sont pas passées comme arguments à la fonction interne explicitement? En ce qui concerne la partie d'interpolation de la question initiale, ce n'était pas le cœur de ma question, mais je reconnais que je n'étais pas assez précis pour commencer, alors c'est sur moi. – ritualmagick

+0

Oui, vous avez raison. La fonction externe fournit le contexte dans lequel la fonction interne est définie et ce contexte est «mémorisé» même après la fin de l'appel de la fonction externe. Différentes invocations de la fonction externe créeront différentes fermetures, de sorte que vous pouvez, par ex. utiliser 'interpolate' pour créer un nombre quelconque de fonctions linéaires par morceaux qui peuvent être utilisées simultanément (en passant, mon code d'interpolation n'était pas très efficace.) Une meilleure approche pourrait être d'utiliser le module' bisect' pour déterminer les deux valeurs de ' xs' à utiliser pour 'N (x)' - plutôt que la recherche linéaire que j'ai utilisée). –