8
votes

La boucle est-elle en boucle dans une boucle sur ce même générateur de sécurité en python?

de ce que je comprends, un pour x dans a_generator: foo (x) code> boucle dans Python est à peu près équivalente à ceci:

for outer_item in a_generator:
    if should_inner_loop(outer_item):
        for inner_item in a_generator:
            foo(inner_item)
            if stop_inner_loop(inner_item): break
    else:
        bar(outer_item)


2 commentaires

Même si votre logique est sonore pour quels éléments sont consommés et quand, cela sera difficile pour quelqu'un d'autre (y compris votre futur moi) à la pièce ensemble, ce qui se passe.


@Jaredgoguen je suis d'accord. Dans mon code actuel, j'ai la boucle interne extraite dans une autre méthode, mais je pensais que l'intention de la question serait plus claire si je n'avais pas une autre méthode.


3 Réponses :


3
votes

Non, ce n'est pas sûr (comme dans, nous n'aurons pas le résultat que nous aurions peut-être attendu).

Considérez ceci: P>

a = (_ for _ in range(20))
for num in a:
    for another_num in a:
        print(another_num)


2 commentaires

Eh bien, dépend du résultat attendu. Si vous incluez l'idée de break que l'OP utilisé, et si vous comprenez qu'il restera itération sur le générateur d'où il était , alors je dirais que vous allez obtenir Comportement attendu, pour les générateurs.


J'ai clarifié ce que je veux dire - ce comportement est ce que je cherche. Merci beaucoup!



2
votes

Ce n'est pas vraiment une réponse à votre question, mais je recommanderais de ne pas le faire parce que le code n'est pas lisible. Il m'a fallu un moment pour voir que vous utilisiez y code> deux fois, même si c'est tout le point de votre question. Ne faites pas de futurs lecteurs devenez confondus par cela. Quand je vois une boucle imbriquée, je ne m'attends pas à ce que vous avez fait et que mon cerveau a du mal à le voir.

Je le ferais comme ceci: P>

def generator_with_state(y):
    state = 0
    for x in y:
        if isinstance(x, special_thing):
            state = 1
            continue
        elif state == 1 and isinstance(x, signal):
            state = 0
        yield x, state

for x, state in generator_with_state(y):
    if state == 1:
        foo(x)
    else:
        bar(x)


3 commentaires

C'est comme ça que je le fais dans mon code réel. J'ai demandé avec le légèrement plus confus, car je pensais que l'intention serait plus claire - boucler sur le générateur à l'intérieur d'une autre boucle. Excuses.


Pas besoin de s'excuser. Ce n'est pas toujours évident ce qui rendra code plus ou moins lisible. Mais je pense que le fait que tout le monde semble confus à propos de votre question démontre mon point.


Relire votre code et c'est en fait ... pas si semblable à ce que je fais. Je ne pouvais que donner un coup d'œil sur mobile, mais regarda similaire; Mon code actuel est que je défini une fonction qui fait la boucle, alors si la chose spéciale se produit, appelant cette fonction au lieu d'avoir une boucle intérieure. Malheureusement, ce modèle ne fonctionnerait pas pour moi; En dehors de cela, ça a l'air bien!



6
votes

TL; DR: Il est sûr avec CPPHON (mais je n'ai pas pu trouver de spécification de cela), bien que cela puisse ne pas faire ce que vous voulez faire.


Tout d'abord, parlons de votre première hypothèse, l'équivalence. p>

A pour la boucle appelle en fait d'abord iter () code> sur l'objet, puis exécute suivant () code> sur son résultat, jusqu'à ce qu'il obtienne une STOVITÉTRAITATION CODE>. P>

Voici le byTecode pertinent (une forme de python à faible niveau, utilisée par l'interprète lui-même): P>

>>> import dis
>>> def f():
...  for x in y:
...   print(x)
... 
>>> dis.dis(f)
  2           0 SETUP_LOOP              24 (to 27)
              3 LOAD_GLOBAL              0 (y)
              6 GET_ITER
        >>    7 FOR_ITER                16 (to 26)
             10 STORE_FAST               0 (x)

  3          13 LOAD_GLOBAL              1 (print)
             16 LOAD_FAST                0 (x)
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             22 POP_TOP
             23 JUMP_ABSOLUTE            7
        >>   26 POP_BLOCK
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE


3 commentaires

Hé, je pense que parce que j'ai mal formulé ma question, j'ai eu des réponses à la mauvaise question. Pourriez-vous me faire une faveur et vérifier cette réponse avec la question légèrement mise à jour?


Le point 1 était ce que j'ai compris comme une sécurité, alors oui, c'est sûr. Le point 2 décrit ce que cela fait réellement (que j'ai adressé dans les deux derniers paragraphes)


Impressionnant! Je n'ai pas bien compris le dernier petit peu de ithertools.tee () , mais cela semblait avoir abordé la question avec la mauvaise idée que j'ai laissée tout le monde.