This question already has answers here:
Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of those?
(8 answers)
Closed 6 months ago.
I'm triggering loop within loop in Python, if one of the multiple conditions ("or") is met.
The script seems to skip the "if" statement and enters inner loop without meeting required conditions.
Code
# Begin TestCase
# Main logic: execute RemoteController macro, if expected state == true, set 'Success', else: Fail
for macroname_n in range (32):
handler("RemoteController", "SET", "[{0}_{1}_{2}]".format(testcase, macroname_n, platform), "")
result = pbc_json(disk, testcase_area, testcase, platform, filename_n, coord_n)
filename_n += 1
coord_n += 1
if macroname_n == 15 or 20:
success_counter = 0
for extra_loop in range(15):
handler("RemoteController", "SET", "\"down 4\"", "")
result = pbc_json(disk, testcase_area, testcase, platform, filename_n, coord_n)
filename_n += 1
if result >= 50:
success_counter += 1
if success_counter <> 15:
result = 0
Thanks in advance!
This line does not do what you want:
if macroname_n == 15 or 20:
This is parsed as follows:
if (macroname_n == 15) or (20):
Since 20 is always true in a boolean context, the statement is always true. What you actually want is this:
if macroname_n in (15, 20):
20 always evaluates to true in a boolean context. Therefore, macroname_n == 15 or 20 is always true.
You probably want to write:
if macroname_n == 15 or macroname_n == 20:
success_counter = 0
# ...
if macroname_n == 15 or 20:
should be:
if macroname_n == 15 or macroname_n == 20:
otherwise will it always read 20 as true.
Related
Here is the function i defined:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
if data[i:i + l] is field:
while data[i - l: i] == data[i:i + l]:
count = count + 1
i = i + 1
else:
print("OK")
if final == 0 or count >= final:
final = count
return final
a = input("Enter the field - ")
b = input("Enter the data - ")
print(count_longest(a, b))
It works in some cases and gives incorrect output in most cases. I checked by printing the strings being compared, and even after matching the requirement, the loop results in "OK" which is to be printed when the condition is not true! I don't get it! Taking the simplest example, if i enter 'as', when prompted for field, and 'asdf', when prompted for data, i should get count = 1, as the longest iteration of the substring 'as' is once in the string 'asdf'. But i still get final as 0 at the end of the program. I added the else statement just to check the if the condition was being satisfied, but the program printed 'OK', therefore informing that the if condition has not been satisfied. While in the beginning itself, data[0 : 0 + 2] is equal to 'as', 2 being length of the "field".
There are a few things I notice when looking at your code.
First, use == rather than is to test for equality. The is operator checks if the left and right are referring to the very same object, whereas you want to properly compare them.
The following code shows that even numerical results that are equal might not be one and the same Python object:
print(2 ** 31 is 2 ** 30 + 2 ** 30) # <- False
print(2 ** 31 == 2 ** 30 + 2 ** 30) # <- True
(note: the first expression could either be False or True—depending on your Python interpreter).
Second, the while-loop looks rather suspicious. If you know you have found your sequence "as" at position i, you are repeating the while-loop as long as it is the same as in position i-1—which is probably something else, though. So, a better way to do the while-loop might be like so:
while data[i: i + l] == field:
count = count + 1
i = i + l # <- increase by l (length of field) !
Finally, something that might be surprising: changing the variable i inside the while-loop has no effect on the for-loop. That is, in the following example, the output will still be 0, 1, 2, 3, ..., 9, although it looks like it should skip every other element.
for i in range(10):
print(i)
i += 1
It does not effect the outcome of the function, but when debugging you might observe that the function seems to go backward after having found a run and go through parts of it again, resulting in additional "OK"s printed out.
UPDATE: Here is the complete function according to my remarks above:
def count_longest(field, data):
l = len(field)
count = 0
final = 0
n = len(data)
for i in range(n):
count = 0
while data[i: i + l] == field:
count = count + 1
i = i + l
if count >= final:
final = count
return final
Note that I made two additional simplifications. With my changes, you end up with an if and while that share the same condition, i.e:
if data[i:i+1] == field:
while data[i:i+1] == field:
...
In that case, the if is superfluous since it is already included in the condition of while.
Secondly, the condition if final == 0 or count >= final: can be simplified to just if count >= final:.
I'm trying to write an if else statement in shorthand.
An if else to check a value and increment if it has not reached a value, otherwise minus a set number.
As an if else this works, but trying to do this as a shorthand version and am stuck.
Is the issue you cant use -= or += in this context? Any help to understand would be appreciated.
Have tried day-=7 if day == 7 else day+=1 - but know this is wrong as the var is already referenced on the left.
If else works fine
day = 5
if day == 7:
day-=7
else:
day+=1
Trying to write this in shorthand and I get an error on the right day+=1 as this is clearly incorrect. Looking for some advice on how to increment the day value if day != 7
day = 5
day-=7 if day == 7 else +=1
The +=1 throws an error.
Expect day to be 6
day += -7 if day == 7 else 1
The way you read this is "Add negative 7 to day if day == 7, otherwise, add 1 to day"
Dagorodir's original answer does not work, because it will subtract (day + 1) from the current value of day if day != 7. So using your example with the the starting value of 5 for day, the result of running the code from the other answer is -1.
You are right in saying that you cannot use the assignment operators -= or += in some places in the context of a "conditional expression" in Python. My understanding is that the shorthand if-else is an expression, not a statement, as seen in your initial example. You cannot make assignments on the right hand side but instead specify the return value if false, and the return value (or assignment to the variable) if true on the left.
In your second attempt, on the right hand side, you have used the assignment operator without a variable. If you wanted the evaluation of the condition to take more complex values, you could assign to variables:
day = 5
ret_false = day + 1
ret_true = day - 7
ret_true if day == 7 else ret_false
Refer to Samantha's answer for more elegant solution: the += increment assignment operator is used for evaluation of either True or False in the expression - so -7 is necessary on the left, while += 1 is assigned otherwise. I repeat the inverse of the solution in her answer to illustrate the mechanics of the syntax; using the decremental -= operator on the left enforces its use on the right -
day -= 7 if day == 7 else -1
Following the above logic, my original suggestion below uses the decremental -= assignment operator on the left; day-7 is returned if true, while day-(day+1) is returned if false. Thanks to Samantha for pointing this out.
Original
Try:
day -= 7 if day == 7 else day + 1
There are many questions regarding this: here and here, for example.
To me this is the most readable, using modulo arithmetic
day = 5
day = (day + 1) % 7
print(day)
# result 6
day = 6
day = (day + 1) % 7
print(day)
# result 0
I have two option for you:
day = day + (-7 if day == 7 else 1)
OR
day = day -7 if day == 7 else day + 1
I have the following code. It is basically a balckjack function. It should return the sum of 3 numbers is less then 21. If bigger and it has 11 as one of the numbers it should deduct 10 from it. If after the deduction the sum is still bigger han 21 it should return 'BUST'. In the training José solved the last part with making in the elif the sum smaller or equal to 31, which of course is a nice way to have then just 'BUST' in an else and not nested into the elif.
However I want to do de excercise my way with nesting the 'BUST' into the elif. So far no luck, I am guessing, because of the return I cannot put any condition afterwards.
Do you guys have any solution to make the 'BUST' a sub-condition of the elif? Here is my code, which does not work.
def blackjack(a,b,c):
added = sum([a,b,c])
if added <= 21:
return added
elif added > 21 and 11 in [a,b,c]:
return added -10
busted = added -10
if busted > 21:
return 'BUST'
It should give the following if called:
blackjack(5,6,7) --> 18
blackjack(9,9,9) --> 'BUST'
blackjack(9,9,11) --> 19
You can use a ternary expression on your return:
def blackjack(a,b,c):
added = sum([a,b,c])
if added <= 21:
return added
elif added > 21 and 11 in [a,b,c]:
return (added-10) if (added-10 <= 21) else "BUST-11"
return "BUST"
print( blackjack(5,6,7) )
print( blackjack(9,9,9) )
print( blackjack(9,9,11) )
print( blackjack(10,11,11) )
Output:
18
BUST
19
BUST-11
See Does Python have a ternary conditional operator?
You will still need the fall-trough "BUST" (for >21 w/o 11 in it) anyway - so the else solution is cleaner.
def blackjack(a,b,c):
added = sum([a,b,c])
if added <= 21:
return added
elif added > 21 and 11 in [a,b,c]:
busted = added -10
if busted > 21:
return 'BUST'
return busted
If busted > 21 is true it return 'BUST', if not it moves on to next statement and returns busted. I dont exactly understand why you would need another method but if you want to return two different things based on a condition. if/elif or if/else block are a must.
I'm solving this HackerRank challenge:
Alice has a binary string. She thinks a binary string is beautiful if and only if it doesn't contain the substring '010'.
In one step, Alice can change a 0 to a 1 or vice versa. Count and print the minimum number of steps needed to make Alice see the string as beautiful.
So basically count the number of '010' occurrences in the string 'b' passed to the function.
I want to increment i by 2 once the if statement is true so that I don't include overlapping '010' strings in my count.
And I do realize that I can just use the count method but I wanna know why my code isn't working the way I want to it to.
def beautifulBinaryString(b):
count = 0
for i in range(len(b)-2):
if b[i:i+3]=='010':
count+=1
i+=2
return count
Input: 0101010
Expected Output: 2
Output I get w/ this code: 3
You are counting overlapping sequences. For your input 0101010 you find 010 three times, but the middle 010 overlaps with the outer two 010 sequences:
0101010
--- ---
---
You can't increment i in a for loop, because the for loop construct sets i at the top. Giving i a different value inside the loop body doesn't change this.
Don't use a for loop; you could use a while loop:
def beautifulBinaryString(b):
count = 0
i = 0
while i < len(b) - 2:
if b[i:i+3]=='010':
count += 1
i += 2
i += 1
return count
A simpler solution is to just use b.count("010"), as you stated.
If you want to do it using a for loop, you can add a delta variable to keep track of the number of positions that you have to jump over the current i value.
def beautifulBinaryString(b):
count = 0
delta = 0
for i in range(len(b)-2):
try:
if b[i+delta:i+delta+3]=='010':
count+=1
delta=delta+2
except IndexError:
break
return count
You don't need to count the occurrences; as soon as you find one occurrence, the string is "ugly". If you never find one, it's beautiful.
def is_beautiful(b):
for i in range(len(b) - 2):
if b[i:i+3] == '010':
return False
return True
You can also avoid the slicing by simply keeping track of whether you've started to see 010:
seen_0 = False
seen_01 = False
for c in b:
if seen_01 and c == '0':
return False
elif seen_1 and c == '1':
seen_01 = True
elif c == '0':
seen_0 = True
else:
# c == 1, but it doesn't follow a 0
seen_0 = False
seen_01 = False
return True
I wrote a little script in order to return a list of 'characters' from a list of values :
List of values :
11
11
14
6
6
14
My script :
# -*- coding:utf-8 -*-
import numpy as np
data = np.loadtxt('/Users/valentinjungbluth/Desktop/produit.txt',
dtype = int)
taille = len(data)
for j in range (0, taille) :
if data[j] == 1 or 2 or 3 or 11 or 12 or 13 :
print 'cotisation'
if data[j] == 14 :
print 'donation'
else :
print 'part'
What I need to get :
'cotisation'
'cotisation'
'donation'
'part'
'part'
'donation'
What I get :
cotisation
part
cotisation
part
cotisation
donation
I don't see where I made an error ..
If someone could read my script and maybe correct him ?
Thank you
Try:
for j in range(0, taille):
if data[j] in {1, 2, 3, 11, 12, 13}:
print ("cotisation")
elif data[j] == 14:
print ("donation")
else:
print ("part")
There are a couple issues here:
if x == 1 or 2 or 3 or ... does not do what you are expecting.
Each clause is evaluated independently, so python does not know you are implying if x == 1 or x == 2 or x == 3, etc. It instead interprets this as if x == 1 or if 2 or if 3 ... if 2 and the like is actually a sensical if statement in python and is basically tantamount to asking if True (all non-zero integer values have a "truthiness" of True). So your statement is really equivalent to if data[j] == 1 or True or True or True or True, which reduces to if True. In other words, the condition is always satisfied regardless of the value. What you probably meant was:
if data[j] == 1 or data[j] == 2 or data[j] == 3 or data[j] == 11 ...
Your if-else construction has two blocks when one is intended
Currently boils down to something like the following in pseudocode:
if some condition:
print 'something'
now regardless of the first condition, if some other disjoint condition:
print 'something else'
otherwise:
print 'does not match other condition'
In other words, by using two ifs, the second if block, of which the else is a part, is treated as completely independent of the first if. So cases that satisfy the first condition could also satisfy the else, which is sounds like is not what you wanted as each character should print exactly once. If you want it to be 3 disjoint cases, you need to use elif instead so it is all considered part of a single block:
E.g.
if condition:
print 'something'
elif other condition:
print 'something else'
else:
print 'does not match EITHER of the two above condtions'
Scimonster point out your 1st issue in the code, you need elif for the second if.
The 2nd issue is the or part, your if condition is being intepret as
if (data[j] == 1) or 2 or 3 or 11 or 12 or 13
You could fixed them as below
if data[j] in [1, 2, 3, 11, 12, 13] :
print 'cotisation'
elif data[j] == 14 :
print 'donation'
else :
print 'part'
if data[j] == 1 or 2 or 3 or 11 or 12 or 13 :
print 'cotisation'
if data[j] == 14 :
print 'donation'
else :
print 'part'
You have two separate ifs here, and one has an else. They should all flow together, so the second should be elif.