mdhoney
mdhoney

Reputation: 59

Python "while" loop not ending as expected

I am trying to be "Python-esque" in my code, where I am trying to call three functions, in succession, the second one only gets called if the first one doesn't produce a result, and the third one only if the first and second don't...

sky = "none"
while sky == "none":
    sky = searchUnguided(inframe, skysearch, debug=debug)
    sky = searchPQ(ad, skysearch, maxpq, debug=debug)
    sky = searchAB(ad, maxpq, debug=debug)
    break

Each of these functions searchUnguided, searchPQ and searchAB returns a value, which is none by default but can be changed to something else. It's these "something else" cases that I want to stop the while sky == "none" loop on. Yet, it doesn't work as I expect it to, and all three functions are called even when the first one returns something other than none.

Example of one function (have verified it returns non-none values as expected):

def searchUnguided(filename, skysearch, debug=False):
    utdate = filename[1:9]
    n = int(filename[11:15])
    skyout = "none"
    for ndiff in skysearch:
        sn = n - ndiff
        skyim = "N" + utdate + "S" + str(sn).zfill(4)
        fskyim = os.path.join(rawdir, skyim + ".fits")
        try:
            sad = AD.read(fskyim, mode='readonly')
            if getstate(sad, "frozen") != "none":
                # we found a sky!
                skyout = skyim
                break
        except:
            continue
    return skyout

Am I misunderstanding the way the while loop works? I can always use nested if statements but that seems so long-winded...

Thanks in advance!

Upvotes: 0

Views: 4011

Answers (4)

Blckknght
Blckknght

Reputation: 104702

I think your understanding of what a while loop does is incorrect. The loop condition is only checked at the top of the loop, so, once before searchUnguided is called and never again (since you have a break statement after the last call). It is not tested in between the function calls.

What I think you want is something like this:

sky = searchUnguided(searchUnguided(inframe, skysearch, debug=debug)
if sky == "none":
    sky = searchPQ(ad, skysearch, maxpq, debug=debug)
    if sky == "none":
        sky = searchAB(ad, maxpq, debug=debug)
        # you may want another "if" here to do something else if sky is still "none"

Upvotes: 1

akrishnamo
akrishnamo

Reputation: 459

The while loop will have no effect in this case, because the first time around it will evaluate to true and there will be no evaluation the second time around due to the break

looks like ifs are not a bad way to go

Upvotes: 1

Erwin
Erwin

Reputation: 3366

This line: while sky == "none": The while-loop condition will only be checked after every loop. So in this case all functions would be executed before the next check of the condition will take place. However, due to the break; the while loop will be terminated anyhow. This makes this while loop just a rewritten version of a regular if-condition.

Upvotes: 0

FortMauris
FortMauris

Reputation: 167

The function searchUnguided() breaks out from its own local FOR loop if it finds an answer other than none. It doesn't breaks out from the while loop. When the code is run, Line 2 checks if sky == 'none', if yes it continues to run. On Line 3, assuming that sky is being changed, it does not have any checks on it (Remember, the check is on Line 2). Therefore, the rest of the code runs before the break on Line 6 comes in.

I will probably do something like this:

sky = "none"
while sky == "none":
    sky = searchUnguided(inframe, skysearch, debug=debug)
    if sky != "none":
        break
    sky = searchPQ(ad, skysearch, maxpq, debug=debug)
    if sky != "none":
        break
    sky = searchAB(ad, maxpq, debug=debug)
    break

There might be a better answer, but this will work.

Upvotes: 0

Related Questions