Python 3.6.2 not running loops over a single value - python

In my code I have implemented a loop where the lower and upper bounds are variable, and it can happen that lower and upper bound are the same. In this case, Python skips the loop.
for i in range(low_, high_):
print(i)
Is there a way to fix this in the definition of the loop?

yes, when low == high, the loop does not enter.
Loops run from start to the inclusion of (end - 1); it is therefore entirely normal behavior
In the case where low == high, you must test to print the low. (credits to #Michael_heath for catching a mistake in the comments)
for i in range(low_, high_):
print(i)
if low_ == high_:
print(low_)

Try running:
for i in range(low_, high_ + 1):
print(i)
It sounds like you want your loop to start at low_ and get to high_, even if they're the same. So adding the extra '+ 1' should get you what you want.
In general a loop only gets to one less than the second value. If you want to hit that value, adding the extra one should do the trick.

Related

Best way in python to check if a loop is not executed

The title might be misleading, so here is a better explanation.
Consider the following code:
def minimum_working_environment(r):
trial=np.arange(0,6)[::-1]
for i in range(len(trial)):
if r>trial[i]:
return i
return len(trial)
We see that if r is smaller than the smallest element of trial, the if clause inside the loop is never executed. Therefore, the function never returns anything in the loop and returns something in the last line. If the if clause inside the loop is executed, return terminates the code, so the last line is never executed.
I want to implement something similar, but without return, i.e.,
def minimum_working_environment(self,r):
self.trial=np.arange(0,6)[::-1]
for i in range(len(self.trial)):
if r>trial[i]:
self.some_aspect=i
break
self.some_aspect=len(self.trial)
Here, break disrupts the loop but the function is not terminated.
The solutions I can think of are:
Replace break with return 0 and not check the return value of the function.
Use a flag variable.
Expand the self.trial array with a very small negative number, like -1e99.
First method looks good, I will probably implement it if I don't get any answer. The second one is very boring. The third one is not just boring but also might cause performance problems.
My questions are:
Is there a reserved word like return that would work in the way that I want, i.e., terminate the function?
If not, what is the best solution to this?
Thanks!
You can check that a for loop did not run into a break with else, which seems to be what you're after.
import numpy as np
def minimum_working_environment(r):
trial = np.arange(0, 6)[::-1]
for i in range(len(trial)):
if r > trial[i]:
return i
return len(trial)
def alternative(r):
trial = np.arange(0, 6)[::-1]
for i in range(len(trial)):
if r > trial[i]:
break
else:
i = len(trial)
return i
print(minimum_working_environment(3))
print(minimum_working_environment(-3))
print(alternative(3))
print(alternative(-3))
Result:
3
6
3
6
This works because the loop controlling variable i will still have the last value it had in the loop after the break and the else will only be executed if the break never executes.
However, if you just want to terminate a function, you should use return. The example I provided is mainly useful if you do indeed need to know if a loop completed fully (i.e. without breaking) or if it terminated early. It works for your example, which I assume was exactly that, just an example.

I'm trying to find happy numbers but my program goes into an endless loop

I've done everything in my ability to try to do this without any functions and only while loops (as said by my teacher) please could you find out why, I even tried dry running but it should still work
p.s it doesn't work in either ways of using:
while c!=0 and f<50: or while c!0 or f<50:
happy_num=1
x= [0]*30
f=0
#f is a safety measure so that the program has a stop and doesnt go out of control
happynumbers=" "
number=int(input("input number "))
while happy_num!=31:
c=0
happy=number
while c!=1 or f<50:
integer=number
f=f+1
if integer<10:
a=number
b=0
d=0
elif integer<100:
a=number // 10
b=number % 10
d=0
else:
a=number // 10
bee=number % 100
b=bee // 10
d=number % 10
number=(a*a)+(b*b)+(d*d)
c=number
x[happy_num-1]=happy
if c==1:
happy_num+=1
elif f>49:
print("too many iterations program shutting down")
exit()
number=happy+1
print ("the happy numbers are: ", happynumbers)
Firstly, you say:
It doesn't work in either ways of using: while c!=1 and f<50: or while c!=1 or f<50
You should use the one with and (while c!=1 and f<50:), because otherwise it is useless as a failsafe. Right now your program gets stuck anyways so it might seem to you to not make a difference, I understand that. It's important in general that a failsafe is added with and, and not with or (because true or true == true and true or false == true, so when your loop is infinite, the f<50 failsafe will not make any difference to the truth value of the guard).
Adding print statements to your program, you can see that at around f=30 the program starts to become very slow, but this is not because of some infinite loop or anything; it's because the computations start to become very big at the line:
number=(a*a)+(b*b)+(d*d)
So f never actually reaches 50, because the program gets stuck trying to perform enormous multiplications. So much for your failsafe :/
I am not sure what algorithm you are using to find these happy numbers, but my guess it that there is something lacking in your guard of the inner loop, or some break statement missing. Do you account for the situation that the number isn't a happy number? Somehow you should also exit the loop in that situation. If you have some more background to what the program is supposed to do, that would be very helpful.
Edit: judging from the programming example on the Wikipedia page of happy numbers, you need some way to keep track of which numbers you've already 'visited' during your computations; that is the only way to know that some number is not a happy number.
plus the question i was given was to find the first 30 happy numbers, so the input would 1

How to run a for loop with variable range?

I want to have a Python program like--
for i in range(r):
if (i==2):
#change r in some way
which will run the loop for the new range r, after it gets modified in the if statement.
Even if I change r after the if statement,the for loop runs for the initial r I gave.This must be happening because range(r) gets fixed in the for statement in the first line itself,and is not affected by change in r later on.
Is there a "simple way" to bypass this?
By "simple" I mean that I don't want to add a counter which counts how many times the loop already ran and how many times it need to run again after changing(specifically increasing) r,or by replacing for loop with a while loop.
When you say:
for i in range(r):
range(r) creates a range object. It does this only once when the loop is set up initially. Therefore, any changes you make to r inside the loop have no effect on the performance of the loop, since it's the range object that dictates the number of iterations (it just happens to be initialized with r).
Rule of thumb: If you know how many iterations you need in advance, use a for loop. If you don't know how many iterations you need, use a while loop.
I don't believe this is possible. However, using a while loop and a manual counter is itself an extremely simple way to do this.
The code will look something like this:
i = 0
while i < r:
if i == 2:
# Change r in some way

Check statement for a loop only once

Let’s say I have following simple code:
useText = True
for i in range(20):
if useText:
print("The square is "+ str(i**2))
else:
print(i**2)
I use the variable useText to control which way to print the squares. It doesn’t change while running the loop, so it seems inefficient to me to check it every time the loop runs. Is there any way to check useText only once, before the loop, and then always print out according to that result?
This question occurs to me quite often. In this simple case of course it doesn’t matter but I could imagine this leading to slower performance in more complex cases.
The only difference that useText accomplishes here is the formatting string. So move that out of the loop.
fs = '{}'
if useText:
fs = "The square is {}"
for i in range(20):
print(fs.format(i**2))
(This assumes that useText doesn't change during the loop! In a multithreaded program that might not be true.)
The general structure of your program is to loop through a sequence and print the result in some manner.
In code, this becomes
for i in range(20):
print_square(i)
Before the loop runs, set print_square appropriately depending on the useText variable.
if useText:
print_square = lambda x: print("The square is" + str(x**2))
else:
print_square = lambda x: print(x**2)
for i in range(20):
print_square(i)
This has the advantage of not repeating the loop structure or the check for useText and could easily be extended to support other methods of printing the results inside the loop.
If you are not going to change the value of useText inside the loop, you can move it outside of for:
if useText:
for i in range(20):
print("The square is "+ str(i**2))
else:
for i in range(20):
print(i**2)
We can move if outside of for since you mentioned useText is not changing.
If you write something like this, you're checking the condition, running code, moving to the next iteration, and repeating, checking the condition each time, because you're running the entire body of the for loop, including the if statement, on each iteration:
for i in a_list:
if condition:
code()
If you write something like this, with the if statement inside the for loop, you're checking the condition and running the entire for loop only if the condition is true:
if condition:
for i in a_list:
code()
I think you want the second one, because that one only checks the condition once, at the start. It does that because the if statement isn't inside the loop. Remember that everything inside the loop is run on each iteration.

What is the best way on Python to identify if a break occurred on the last element iteration due to a condition within?

I saw some similar questions to this but none seems to address this is specific question so I don't know if I am overlooking something since I am new to Python.
Here is the context for the question:
for i in range(10):
if something_happens(i):
break
if(something_happened_on_last_position()):
# do something
From my C background, if I had a for (i=0;i<10;i++) doing the same thing with a break, then the value of i would be 10, not 9 if the break didn't occur, and 9 if it occurred on the last element. That means the method something_happened_on_last_position() could use this fact to distinguish between both events. However what I noticed on python is that i will stop on 9 even after running a successful loop without breaks.
While make a distinction between both could be as simple as adding a variable there like a flag, I never liked such usage on C. So I was curious, is there another alternative to do this or am I missing something silly here?
Do notice that I can't just use range(11) because this would run something_happens(10). It is different on C on this since '10' would fail on the condition on the for loop and would never execute something_happens(10) (since we start from index 0 here the value is 10 on both Python and C).
I used the methods just to illustrate which code chunk I was interest, they are a set of other conditions that are irrelevant for explaining the problem.
Thank you!
It works the other way:
for i in range(10):
if something_happens(i):
break
else: # no break in any position
do whatever
This is precisely what the else clause is for on for loops:
for i in range(10):
if something_happens(i):
break
else:
# Never hit the break
The else clause is confusing to many, think of it as the else that goes with all those if's you executed in the loop. The else clause happens if the break never does. More about this: For/else

Categories