Reputation: 1020
my typo error led in the 'while loop' function led me to the following question
from time import sleep
from random import randint
def control_pressure():
pressure = measure_pressure()
while True:
if pressure <= 500:
break
while pressure > 500 and pressure <= 700:
run_standard_safeties()
pressure = measure_pressure()
while pressure > 100: # Here is the typo
run_critical_safeties()
pressure = measure_pressure()
print("Wow! The system is safe...")
def measure_pressure():
pressure = randint(450, 800)
print(f"psi={pressure}", end="; ")
return pressure
def run_standard_safeties():
print("Running standard safeties...")
sleep(0.2)
def run_critical_safeties():
print("Running critical safeties...")
sleep(0.7)
if __name__ == "__main__":
control_pressure()
In the above, I made a typo and checked pressure > 100, while condition. But earlier in the first part of the function, it checked, while pressure <= 500, then break. So technically any value lesser than or equal to 500 should return True and break the function without reaching the pressure > 100 condition.
But this function continued without stopping. Why does it happen?
Thanks
Upvotes: 0
Views: 323
Reputation: 881103
Your scenario is best described sequentially.
Any initial pressure greater than 500 will bypass the break
and continue to the first inner loop. Since you're getting a random value 450..800
(a range of 350
- ranges here may be off by one but they're close enough so as not to matter), this has a probability of about 300/350
(the numerator comes from the 500..800
range) or 85%.
The first inner loop will then run as long as you're getting pressures in the range 500..700
, a probability of about 200/350
, or 57%.
At some point you'll exit that first inner loop and enter the second. And you will enter it because all values in the range 450..800
, that you can possibly get as a pressure, are greater than a hundred.
That means, of course, that you will also never exit that loop because no pressure you ever get after that point will be a hundred or less, which is what's needed to exit the loop.
As an aside, you could actually avoid this loops-within-loops structure by realising that you to get the pressure every iteration of every loop, so that can be made common.
Assuming your typo was to use 100
where you meant 700
(as that marches with mutually exclusive ranges), that can be simplified to:
def control_pressure():
while True:
pressure = measure_pressure()
if pressure <= 500:
print("Wow! The system is safe...")
return
if pressure <= 700:
run_standard_safeties()
else:
run_critical_safeties()
Or, if you want to use the :=
walrus operator(a) (available in Python 3.8+, I think), you could shorten it even further by getting and checking pressure as part of the while
statement:
def control_pressure():
while (pressure := measure_pressure()) > 500:
if pressure <= 700:
run_standard_safeties()
else:
run_critical_safeties()
print("Wow! The system is safe...")
(a) So called because, if you rotate it 90° clockwise and squint, it looks like a walrus with its two eyes and two huge tusks.
It basically (in this case) lets you assign a value to a variable as part of checking said variable, so that the value is available for later checks as well.
Upvotes: 2
Reputation: 1003
If the initial number is above 100 and above 500 it will enter the second loop and never stop since it will always be above 100, since your are taking one at random from 450-800.
Upvotes: 0