Why do I need an explicit check in a while statement?

Question:

contig = deque()
contig.append(2)
answer = 0
while contig:
    dist = contig.popleft()
    val = 0
    total = pow(2, val)
    while total < dist:
        val += 1
    if total == dist:
        answer += 1
        val = 0
    elif total > dist:
        answer += 1
        contig.append(dist - pow(2, val - 1))
        val = 0

print(answer)

================================code below this line contains no infinite loop
contig = deque()
contig.append(2)
answer = 0
while contig:
    dist = contig.popleft()
    val = 0
    while pow(2, val) < dist:
        val += 1
    if pow(2, val) == dist:
        answer += 1
        val = 0
    elif pow(2, val) > dist:
        answer += 1
        contig.append(dist - pow(2, val - 1))
        val = 0
print(answer)

All this can be simplified into :

zz = 1
jj = 0
while zz * jj < 10 :
    jj += 1
    print(zz, jj  )
###############################below this line contains an infinite loop
while True:
    z = 1
    j = 0
    r = z + j
    while r < 10:
        j += 1
        print(z, j , r )

Can anyone provide an explanation on why it works this way? It was marked as duplicate and closed by someone, but I was chatting with a user about it and their explanation was as follows :
enter image description here

No disrespect, but I am not really understanding what is going on for my exmaple. They linked Variable X not updating when variables that should effect X change this post, but I am also not seeing the relationship here. At any rate, could someone provide an explanation in regards to the examples that I am giving? According to user it doesn’t have anything to do pass by reference or value, Thanks a lot all.
Also, the user says that total = pow(2,val) sets the value of total once and never updates it again, but why should it not update? the program does check if total < dist, thats in the while loop. As far as I can see, the issue is that it always refers to the first time I declared it. Why is this case? I also tested this in c++ and am getting the same results.

Edit* right total is not modified, but total is defined to be comprised of 2 values outside of the loop, and those values are updated, so why doesn’t this update reflect in the while condition check? Just want to leave this here since if it was unclear to one user it probably is to others

I think im doing a terrible job asking my question so I just want to reclarify

while True:
    z = 1
    j = 0
    r = z + j
    while r < 10:
        j += 1
        print(z, j , r )

r always remains one, putting this code in an infinite loop. However, i defined r = z + j and j is getting incremented. I don’t understand why the compiler is not re calculating what r is when it checks the condition

Asked By: jojo33

||

Answers:

It took me a bit to zero in on, but I think the problem you’re asking about is this infinite loop:

    while total < dist:
        val += 1

Neither total nor dist are modified by the statement val += 1. It is therefore safe to say that if you ever get inside that loop, you will not get out of it; you will never execute any line outside the loop that might change either total or dist.

Note that this line:

total = pow(2, val)

does not alias the name total to the expression pow(2, val), as if you did (for example) the following in C:

#define total pow(2, val)

Instead, when you do an assignment (in Python or in almost any other language), the expression on the right-hand side of the assignment is evaluated, and its resulting value (at that exact moment) is bound to the left-hand side of the assignment. Hence after you run:

total = pow(2, val)

total has the value of 2 to the power of whatever val was at the time you did the assignment. If val was 0, then pow(2, val) returned 1, and total is now 1. total is not bound to the expression pow(2, val), or even to the expression pow(2, 0), it is bound to the number 1 and nothing more — nothing in total links it to the expression that originally produced that 1. If you print total, you will get 1, and only 1, until you assign some other value to total.

If you wanted total to dynamically update inside your loop, the solution would be to make it a function, like this:

    total = lambda: pow(2, val)
    while total() < dist:
        val += 1

total is now bound to a function that has the body pow(2, val), and to get a value from it, we call it with the () operator. This causes the body of the function to be evaluated right then, producing a new result based on whatever value val currently has.

It would be simpler, though, to just update total whenever you update val:

    total = pow(2, val)
    while total < dist:
        val += 1
        total = pow(2, val)

or even:

    total = pow(2, val)
    while total < dist:
        val += 1
        total *= 2
Answered By: Samwise
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.