Cette réponse explique comment créer des cas de test de manière dynamique.
Le code de la réponse: p> J'ai testé et ça marche, mais je ne peux pas comprendre comment p> Comment? P > J'ai du mal à comprendre le lambda Self: code> magie en jeu ici, principalement: p>
FuncTools.Partial () code> (c.-à-d. Pour créer une fonction d'emballage avec un paramètre extra em> qui n'est pas encore connu) li>
auto code> un mot clé significatif ou
lambda spam code> fonctionnerait aussi bien? LI>
.check () code> est parfaitement bien en dehors de la classe code> ES Scope? Li>
lambda code>
(sans parler de cela Je suis d'accord avec Guido et Alex que celui-ci est strong> une vue et je veux em> à faire sans:) li>
ol> p>
3 Réponses :
lambda renvoie une fonction. Alors, ch (i, j) est une fonction 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. P>
Cela signifie p>
Après la boucle, la classe de tests obtient plusieurs méthodes appelées check_i_j p> li>
chacun d'eux a des valeurs i et j clôturées em> en elle p> li>
chacun d'entre eux a son 1ère paramètre appelé Self Code> Est-ce que son argument, et i et j sont clôturés em> à l'intérieur de celui-ci p>
auto code> 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> li>
ul>
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 code> et
j code> à 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.
Tout d'abord: la Lambda est renvoyée à partir d'une fonction pour empêcher que les valeurs modifiées de comparer à ce qui suit: p> Cela ne fonctionnera pas comme prévu, car tous les Lambdas partagent la même espace de noms et utiliseront les valeurs de Nous pourrions obtenir la même chose en enregistrant les valeurs actuelles de 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) P>
blockquote> pas vraiment. Il appelle simplement la méthode est un mot clé significatif ou un spam Lambda fonctionnerait aussi bien? P>
blockQuote> Quel est le point que Lambda a évalué? P>
blockquote> dès que Comment se fait-il que le .check () est parfaitement bien en dehors des classes de la scorie? P>
BlockQuote> Parce que c'est à l'intérieur d'une Lambda ne sera appelé plus loin avec une instance de i code> et
j code> seront utilisées ultérieurement.
i code> et
j code> 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 code> et
j code> au moment où la fonction est appelée. p>
i code> et
j code> comme arguments par défaut de la Lambda. Pour faire bonne mesure, utilisons également
iTerTools.Product code> pour éviter la boucle imbriquée: p>
check (i, j) code> 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 Code> Code> Classe. P>
spam code> fonctionnerait aussi bien. Ils choisissent
auto code> en raison de la convention car la Lambda représente une méthode. P>
test_ [i] _ [j] () code> est appelé une instance de
tests code>. P>
tests code> comme l'argument
auto p> p> p>
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 code>
@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) code> renvoie une fonction réelle:
retour Lambda * args, ** kw: f (* args, ** kw) code>. Ensuite, nous pouvons utiliser
méthodalcaller code> comme suit:
make_func (méthodalcaller ("cocher", 1, 2)) code>.
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 code>). 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.
est équivalent à p> dans votre exemple particulier, les fonctions créées sont une instance méthodes. Ainsi, par exemple, vous pouvez écrire: p> ce qui serait équivalent à: p> maintenant, puisque les identificateurs sont générés Dynamiquement, d'où l'utilisation de Non, pas vraiment. En fait, serait devenu p> La première argument de la méthode d'instance doit toujours être l'instance. La convention Ce n'est pas. C'est a_function = lambda x: do_something_with (x) code>
setattr code>. p>
FuncTools.Partial () code> (c'est-à-dire pour créer une fonction d'emballage avec un supplément
paramètre qui n'est pas encore connu) li>
ol>
BlockQuote>
partiel code> pourrait être utilisé ici aussi. P>
auto code>, mais vous pouvez utiliser n'importe quel autre nom. Je ne le conseillerais pas, car cela rendra votre code plus difficile à lire et à comprendre. P>
lambda code> crée une fonction anonyme, qui est évaluée sur appel. P>
self.check () code>, où
auto code> est une instance de
tests code> classe. P> p>
En réalité, opérateur.methodcaller ("cocher", 1, 2) code> est préférable sur
partiel code> 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 code> est quelque chose d'opposé de
lambda code>, 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) code> Trick ne fonctionne pas (mais non plus
Tests.method = opérateur.methodcaller ("cocher", 1, 2) code>). 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.