8
votes

Que fait la Lambda: faire

Cette réponse explique comment créer des cas de test de manière dynamique.

Le code de la réponse: xxx

J'ai testé et ça marche, mais je ne peux pas comprendre comment Comment?

J'ai du mal à comprendre le lambda Self: magie en jeu ici, principalement:

  1. est la lambda utilisée ici pour effectuer l'opposé exact de FuncTools.Partial () (c.-à-d. Pour créer une fonction d'emballage avec un paramètre extra qui n'est pas encore connu)
  2. est auto un mot clé significatif ou lambda spam fonctionnerait aussi bien?
  3. De quel point est-ce que Lambda est évalué?
  4. Comment se fait-il que le .check () est parfaitement bien en dehors de la classe ES Scope?
  5. Comment faites-vous cela sans lambda? - Si je comprends bien, Vous devriez pouvoir faire sans lambda (sans parler de cela Je suis d'accord avec Guido et Alex que celui-ci est une vue et je veux à faire sans:)

0 commentaires

3 Réponses :


3
votes

lambda renvoie une fonction. Self Est-ce que son argument, et i et j sont clôturés à l'intérieur de celui-ci

Alors, ch (i, j) est une fonction de i et j que retourne une fonction de auto . .

Self n'a pas de sens magique ici comme rien dans Python - chaque variable et toutes les fonctions sont explicites, à l'exception de certains bâtiments. Mais dès que ces méthodes sont attachées à la classe, auto devient leur 1er argument.

Cela signifie

  • Après la boucle, la classe de tests obtient plusieurs méthodes appelées check_i_j

  • chacun d'eux a des valeurs i et j clôturées en elle

  • chacun d'entre eux a son 1ère paramètre appelé auto qui est une bonne cause qu'ils sont définis à l'intérieur de la classe, ils sont des méthodes d'instance, et donc leur 1er paramètre doit être appelé auto par convention < / p>


6 commentaires

BTW, i chose que le code pourrait être très simplifié en écrivant simplement SETATTR (tests, "Test_% r_% r"% (i, j), Lambda Self: auto.Check (i, j)))


Non, cela fait quelque chose de complètement différent.


@Niklasb. Veuillez expliquer - quelle est la différence entre définir la fonction ch et l'appeler instantanément et simplement la valeur de sa valeur. I et J sont enfermés quand même, non?


Tous les Lambdas partageront la même fermeture. Ils travailleront tous avec les valeurs de i et j à la fin des boucles. Vérifiez ma réponse pour plus de détails. L'appel de la fonction est utilisé dans l'autre réponse pour forcer la création d'une nouvelle fermeture pour chaque Lambda.


Je connais ce problème dans JS, je ne m'attendais pas à ce qu'il soit applicable à Python. Bien que maintenant je réalise que c'est la même chose ici


Ce n'est pas un problème, il vous suffit de prendre conscience de cela.



5
votes

Tout d'abord: la Lambda est renvoyée à partir d'une fonction pour empêcher que les valeurs modifiées de i et j seront utilisées ultérieurement.

comparer à ce qui suit: xxx

Cela ne fonctionnera pas comme prévu, car tous les Lambdas partagent la même espace de noms et utiliseront les valeurs de i et j après la fin de la boucle. Si nous utilisons un appel de fonction distinct, nous introduisons une nouvelle fermeture chaque fois que cela capture les valeurs de i et j au moment où la fonction est appelée.

Nous pourrions obtenir la même chose en enregistrant les valeurs actuelles de i et j comme arguments par défaut de la Lambda. Pour faire bonne mesure, utilisons également iTerTools.Product pour éviter la boucle imbriquée: xxx

est la lambda utilisée ici pour effectuer l'opposé exact de FuncoTools.Partial () (c'est-à-dire pour créer une fonction d'emballage avec un paramètre supplémentaire qui n'est pas encore connu)

pas vraiment. Il appelle simplement la méthode check (i, j) sur tout ce qu'il est donné comme un argument. Ceci est utilisé ici pour ajouter de manière dynamique des méthodes aux tests Classe.

est un mot clé significatif ou un spam Lambda fonctionnerait aussi bien?

spam fonctionnerait aussi bien. Ils choisissent auto en raison de la convention car la Lambda représente une méthode.

Quel est le point que Lambda a évalué?

dès que test_ [i] _ [j] () est appelé une instance de tests .

Comment se fait-il que le .check () est parfaitement bien en dehors des classes de la scorie?

Parce que c'est à l'intérieur d'une Lambda ne sera appelé plus loin avec une instance de tests comme l'argument auto


7 commentaires

Ok "pas vraiment. Cela appelle simplement la méthode chèque (i, j) sur tout ce qu'il est donné comme un argument. Ceci est utilisé ici pour ajouter de manière dynamique des méthodes à la classe de tests." était la chose que je ne me suis pas réalisée. Maintenant que vous en parlez, il est évident (jeu de mots)


La modification de méthodalCaller (qui rendrait le code plus lisible aussi, imo) me donne TypeError: ModyCaller attendu 1 arguments, obtenu 0


@Kimvais: C'est très étrange. Il semble que la fonction ne soit pas liée correctement lorsqu'il est attribué à l'attribut de classe. Ceci pourrait être dû au fait que ce n'est pas une vraie Lambda, mais une fonction définie sur le côté C de Python. Je suppose que je vais ouvrir une question distincte pour cela.


@Kimvais: En attendant, vous pouvez également utiliser le truc d'argument par défaut. J'ai édité ma réponse.


Une autre façon serait d'utiliser définir une fonction make_func (f) renvoie une fonction réelle: retour Lambda * args, ** kw: f (* args, ** kw) . Ensuite, nous pouvons utiliser méthodalcaller comme suit: make_func (méthodalcaller ("cocher", 1, 2)) .


Veuillez poster le lien vers la question que vous ouvrirez ici.


@Kimvais: En fait, j'ai déjà répondu à la question moi-même en utilisant un peu de bon sens. Ce qui se passe, c'est que si vous attribuez une fonction à un attribut de classe, il devient une méthode non liée. Dès qu'une instance est créée à partir de la classe, toutes les méthodes non liées sont liées à l'instance d'objet (c'est-à-dire qu'ils sont partiellement appliqués au nouveau auto ). Maintenant, si nous attribuions quelque chose à un attribut de classe qui n'est pas une fonction, mais seulement appelable, Python ne sait pas que nous voulons que cela devienne une méthode, cela ne le converse pas à une méthode non liée.



5
votes

a_function = lambda x: do_something_with (x)

est équivalent à xxx

dans votre exemple particulier, les fonctions créées sont une instance méthodes. Ainsi, par exemple, vous pouvez écrire: xxx

ce qui serait équivalent à: xxx

maintenant, puisque les identificateurs sont générés Dynamiquement, d'où l'utilisation de setattr .


  1. est le lambda utilisé ici pour effectuer l'opposé exact de FuncTools.Partial () (c'est-à-dire pour créer une fonction d'emballage avec un supplément paramètre qui n'est pas encore connu)

    Non, pas vraiment. En fait, partiel pourrait être utilisé ici aussi. xxx

    serait devenu xxx

    1. est auto-être un mot clé significatif ou que Lambda Spam fonctionnerait aussi bien?

      La première argument de la méthode d'instance doit toujours être l'instance. La convention est de nommer ce paramètre auto , mais vous pouvez utiliser n'importe quel autre nom. Je ne le conseillerais pas, car cela rendra votre code plus difficile à lire et à comprendre.

      1. De quel point est-ce que Lambda est évalué?

        lambda crée une fonction anonyme, qui est évaluée sur appel.

        1. Comment se fait-il que le .check () est parfaitement bien à l'extérieur des classes de la scène?

          Ce n'est pas. C'est self.check () , où auto est une instance de tests classe.


4 commentaires

En réalité, opérateur.methodcaller ("cocher", 1, 2) est préférable sur partiel ici car il utilise la typage du canard et ne nécessite pas d'instance de tests < / code>. Ce commentaire s'applique également à votre réponse à l'autre question.


@Niklasb.: OK, mais la question était si partielle est quelque chose d'opposé de lambda , pas si c'est un meilleur moyen


Bien sûr, peut-être que j'aurais dû mieux l'ajouter à votre autre réponse.


Au fait, je viens de vérifier et il semble que le tests.method = partial (tests.check, i = 1, j = 2) Trick ne fonctionne pas (mais non plus Tests.method = opérateur.methodcaller ("cocher", 1, 2) ). Je soupçonne que la méthode n'est pas liée correctement car ce n'est pas une fonction réelle, mais seulement une appelable, mais je ne suis pas sûr de ce qui se passe.