for loop abbrechen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
peter99
User
Beiträge: 84
Registriert: Samstag 3. August 2013, 21:32

In meinem Code bin ich auf folgendes Problem gestoßen, bei welchem ich nicht ganz sicher bin, wie ich es angehen soll.
In dieser Sequenz soll für verschiedene Qs die Energie berechnet werden. Wenn die Energie < = der möglichen Energie ist, soll der loop fortgesetzt werden, sobald es aber einen Wert überschreitet, soll es den Loop brechen. Nun habe ich aber gelesen, dass break mit Vorsicht zu genießen ist. Außerdem will ich ja den äußersten loop brechen (for i in q) und nicht den inneren. Zudem soll es weiterhin info_contamination returnen, bis eben zu dem Wert von dem break-statement.
Ich bin verwirrt. Vielen Dank, Peter!
(Der untere Teil ist nur damit ihr wisst wie es weitergeht

Code: Alles auswählen

for i in Q:
    info_contamination = compute_energy(i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor)
    for q, numberout, energyout, Vebitout in info_contamination:
        if energyout <= Energy_chosen:
            pass
        if energyout > Energy_chosen:
            break


for q_cont, number_cont, energy_cont, Vebit_cont in info_contamination:
    qdivbya = qcont/a_full
    diffqa = abs(beamqdivbya, qdivbya)
    if diffqa < Diffqa0:
        diffqa = float(diffqa)/float(Qchosen)*A
        result.append(qdivbya)
        set_cells_(table_cont, len(result)-1, nameiso, qcont, a_full, qdivbya, diffqaoverqa, abu)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nun man sollte bei allen Konstrukten vorsichtig sein und nachdenken, das gilt nicht nur fuer Spruenge wie `break`.

Dafuer fuehrt man einen Sentinel-Wert ein, setzt ihn in der inneren Schleife und ueberprueft ihn in der aeusseren:

Code: Alles auswählen

for i in Q:
    info_contamination = compute_energy(i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor)
    energy_below_threshold = True
    for q, numberout, energyout, Vebitout in info_contamination:
        if energyout > Energy_chosen:
            energy_below_threshold = False
            break
    if not energy_below_threshold:
        break
Alternativ koennte man auch den `else`-Zweig von Schleifen nutzen:

Code: Alles auswählen

for i in Q:
    info_contamination = compute_energy(i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor)
    for q, numberout, energyout, Vebitout in info_contamination:
        if energyout > Energy_chosen:
            break
    else:
        continue
    break
Was aber nicht ganz so leicht verstaendlich ist.

Ein ganz anderer Ansatz waere eine Funktion zu nutzen, denn mit einem `return` beendet man beide Schleifen.
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

Dafür gibt es »any«:

Code: Alles auswählen

for i in Q:
    info_contamination = compute_energy(i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor)
    if any(energyout > Energy_chosen for _, _, energyout, _ in info_contamination):
        break
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

for i in Q:
    info_contamination = compute_energy(i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor)

    if any(energyout > Energy_chosen for (_, _, energyout, _) in info_contamination):
        break
Wenn die Bedingung komplexer ist, dann kannst du sie einfach in eine andere Funktion herausziehen.

Deine Bedingung hast du auch etwas seltsam Formulierst. Wenn du ein Konstrukt der Form

Code: Alles auswählen

if BEDINGUNG:
    ...
if not BEDINGUNG:
    ...
hast, dann willst du ein ein else benutzen.

Auch solltest du endlich mal an deiner Namensgebung arbeiten. In Python fangen, per Konvention, Typen mit einem Großbuchstaben an, dass solltest du dir abgewöhnen. Auch sind deine Namen alle absolut nichtssagend. Teilweise machen sie im Kontext der Aufgabe sicher noch Sinn, aber auch da solltest du dir besseres überlegen. Sonst sitzt du in vier Wochen da und verstehst gar nichts mehr. Mit "number_chosen", oder "factor" hast du dann noch vollkommene Worthülsen geschaffen. Was für eine Nummer wurde denn ausgewäht und um was für einen Fakator handelt es sich denn?

Ein wenig Sorgen bereitet auch das i. Dort sollten nur ganzzahlige Indizes drinstecken, alles andere ist extrem unerwartet. Was nun tatsächlich drin steckt verrät der Namen "Q" leider nicht.
Das Leben ist wie ein Tennisball.
BlackJack

@peter99: Was ist denn der Sinn von diesen beiden Schleifen? Soll da am Ende nur `info_contamination` an den entsprechenden Wert gebunden sein? Oder passiert in der inneren Schleife noch irgend etwas anderes was Du uns hier jetzt nicht gezeigt hasst?

Das erste ``if`` macht so nämlich überhaupt keinen Sinn wenn da statt ``pass`` nicht irgendwelcher Code steht, der auch einen Effekt hat.

Falls der Code tatsächlich so aussieht, und die innere Schleife nur testen soll wann das erste `info_contamination` erreicht ist in dem ein `energyout` Wert vorkommt der über `Energy_chosen` kommt, dann lässt sich das mit nur einer ``for``-Schleife testen:

Code: Alles auswählen

    info_contamination = None
    for i in Q:
        info_contamination = compute_energy(
            i, Number_chosen, a_full, Phi, fieldreal, CavmaxReal, factor
        )
        if any(
            energyout > Energy_chosen
            for _, _, energyout, _ in info_contamination
        ):
            break
Vor der Schleife sollte man `info_contamination` an etwas binden was im weiteren Programmverlauf „auffällt”, denn sonst ist es am Ende der Schleife unter Umständen gar nicht, oder an etwas falsches gebunden wenn `Q` leer wahr.

Ich würde trotzdem cofi's Vorschlag mit der eigenen Funktion umsetzen.
peter99
User
Beiträge: 84
Registriert: Samstag 3. August 2013, 21:32

Vielen Dank für die vielen nützlichen Antworten! Ich wusste bis jetzt nicht von der Existenz von any, es scheint aber genau das zu sein, was ich brauche.
Die Namensgebungen machen im Kontext mehr Sinn, z.B. Q steht für Ladung. Es ist schwierig gut verständliche Namen zu finden, die nicht elendslang sind;)
peter99
User
Beiträge: 84
Registriert: Samstag 3. August 2013, 21:32

@BlackJack: die innere Schleife soll nur überprüfen, ob die Energie noch nicht über diesen Wert ist und danach sofort den for i in Q-loop abbrechen, damit keine weiteren (unnützen Werte) kalkuliert werden).
Antworten