Cette question me fait sortir mes cheveux.
Si je fais: p> et l'appelez de mille threads, comment le générateur sait-il quoi Envoyer ensuite pour chaque fil?
Chaque fois que je l'appelle, le générateur enregistre-t-il une table avec le comptoir et la référence de l'appelant ou quelque chose comme ça? P> C'est bizarre. P> S'il vous plaît, clarifiez mon esprit sur celui-là. P> p>
3 Réponses :
Une fonction comme celle-ci, lorsque cela est appelé, retournera un objet générateur. Si vous avez des threads distincts appelant Si deux threads créent chacun un générateur en appelant Un générateur est un objet et son état sera stocké en mémoire, de sorte que deux threads qui créent chacun un Si vous arrivez à cela à partir d'une base C, ceci est pas strong> la même chose qu'une fonction avec suivant () code> sur le même objet générateur, ils interfèrent avec eux. C'est-à-dire que 5 threads appelant
suivant () code> 10 fois chacun obtiendra 50 rendements différents. P>
mygén () code> dans le fil, ils auront des objets de générateur distincts. P>
myGen () code> se réfèrent à des objets distincts. Ce ne serait pas différent de deux threads créant un objet à partir d'une classe code> code>, ils auront chacun un objet différent, même si la classe est la même. P>
statique code> variables. L'état est maintenu dans un objet, non statique dans les variables contenues dans la fonction. P>
Vous n'avez pas vraiment répondu à ma question. Je ne veux pas savoir ce qui va arriver, mais comment ça se passe. Le générateur conserve-t-il une certaine valeur en mémoire lorsqu'un fil crée un générateur?
@PatrickBassut Un objet générateur a un état comme n'importe quel autre objet, alors oui, son état sera stocké en mémoire.
myGen code> n'a pas à se souvenir de rien. Chaque appel à
myGen () code> renvoie un administrateur indépendant. Ces itérables, d'autre part, ont un état: chaque fois que
suivant () code> est appelé sur un, il passe au bon endroit dans le code générateur - lorsqu'un
rendement code> est rencontrée, le contrôle est remis à l'appelant. La mise en œuvre effective est plutôt désordonnée, mais en principe, vous pouvez imaginer qu'un tel itérateur stocke les variables locales, le bytecode et la position actuelle dans le bytecode (A.K.A. Pointeur d'instructions). Il n'y a rien de spécial sur les threads ici. P>
Ouais, les fils étaient juste pour illustrer le problème. Considérant que les générateurs pourraient donner le mauvais aspect de la concurrence (ou quelque chose de plus magique de noir que cela) aux débutants python.
@Patrickbassut: Eh bien, vous pouvez simuler Coroutines avec eux, et avec les coroutine que vous pouvez faire threads verts .
Cela pourrait être plus clair si vous regardez cela de cette façon. Au lieu de: Utilisez: p> alors vous pouvez voir que myGen () n'est appelé qu'une seule fois, et c'est crée em> un nouvel objet, et c'est cet objet qui est itéré. Vous pouvez créer deux séquences dans le même thread, si vous le souhaitez: p> Ceci imprimera 0, 0, 1, 1. P> Vous pouvez accéder à Le même itérateur de deux threads si vous le souhaitez, stockez simplement l'objet générateur dans un global: p> thread 1: p> Cela causerait probablement toutes sortes de ravages. : -) p> p>
Les générateurs sont un peu étranges. Vous pouvez leur assigner aux variables, mais au moment où vous les utilisez réellement, il commence à générer des valeurs de manière «à la demande». Si vous avez attribué l'emplacement de la mémoire d'une fonction, cela est totalement facile à comprendre. Mais autant que je sache, vous ne le faites pas là-bas (vous appelez réellement la fonction dans GEN_OBJ = MYGEN ()). Wow!
Lorsque vous avancez au niveau suivant de Python-Fu sérieux, vous pouvez transmettre des pointeurs vers les méthodes de __Next __ () __ () en tant que rappels GUI. :-)
La plupart du temps, l'instruction "DEF" crée un seul objet de fonction à partir de votre code, qui est exécuté lorsque vous appelez la fonction par nom. Si le code contient "RENDU", Toutefois, le DEF crée des objets de fonction deux i>: celui qui est appelé lorsque vous appelez le nom de la fonction ne vous contient aucun de votre code; Il vient de retourner l'objet générateur. L'objet de fonction qu'il crée à partir de votre code est appelé via l'attribut suivant b> de cet objet générateur, et cette fonction conserve son état dans l'objet générateur et sait comment enregistrer et la restaurer entre les appels.
Merci pour l'explication complète Daniel. Je comprends clairement maintenant (bien qu'il y ait d'autres choses, j'ai encore des doutes qui sortent de cette question de questions). Merci!