This question already has answers here:
"if", and "elif" chain versus a plain "if" chain
(2 answers)
Closed 8 years ago.
grid = 0
if grid == 0:
grid == 1
print("grid 0")
elif grid == 1:
print("grid 1")
grid == 2
When first if statement is true, the second will become true as well.
Is there a statement, to skip the whole if structure otherwise i would have to split the if functions which would double the if statements.
First of all, grid == 1 will not change the value of grid; it's only comparing it to 1, obtaining a boolean value and then immediately throwing it away by not using it. To change the value of a variable, you need to use the assignment operator = (as opposed to the equality comparison operator ==): for example grid = 1.
Also, there's nothing bad with using more if-s it it makes sense. In fact, I would recommended making your program work with as simple and straightforward logic as possible first before trying to "optimize" it or make it more compact.
Also, I would say modifying the value of a variable WHILE you are in the process of testing that variable using a chain of if-elif-else, is considered bad style because it makes your code more complicated and hard to reason about (to yourself and to others).
And in any case, if the first if "fails", any subsequent elifs will not even be looked at, so basically you're forced to use multiple ifs anyway in this case.
As a bonus to get you inspired (and maybe even start reading something like http://learnpythonthehardway.org), here's a demonstration of how = and == could also be used together:
# set `is_wet` to `True` if `precipitation` is "raining", otherwise `False
is_wet = (precipitation == "raining")
The second statement will be skipped alone because you used elif instead of a second if.
if condition_a:
statement_a
elif condition_b:
statement_b:
else:
default_statement
Only one of these conditions will EVER activate. In the case of:
if i > 1:
do_stuff
elif i > 1000:
do_bigger_stuff
if i==2000, only the first statement will execute (do_stuff, not do_bigger_stuff)
Be aware in your example that grid == 1 will not set grid to 1, it will just evaluate False :)
Related
I have everything defined but I am still getting a syntax error in this statement, any idea what I am doing wrong?
screenshot of code
#add collision
if (car.xcor() + 10 = dog.xcor() and car.ycor() + 10 = dog.ycor()):
dog.clear()
else:
pass
The key here is to understand the "=" operator.
A single "=" is an assignment. You're giving a value to a variable.
x = 3
print(x)
>>>> 3
A double "==" is a comparison. You're comparing two objects.
3 == 3
>>>> True
In your case, you are trying to make a comparison. I have not seen the classes that you have created, but at least the first line should be altered to:
if ((car.xcor()+10) == dog.xcor()) and ((car.ycor()+10) == dog.ycor()):
Please notice, I have used excessive parenthesis, because I believe they make it easier to read.
I assume you are trying to make comparisons right?
Use '==' which is the assignment operator instead of simply '='. The assignment operator will evaluate your condition and since the operator outputs a boolean(true or false) value, hence your code would work fine.
Secondly, there was indentation error as well which I have corrected. Check for the indentation in your code. You can use 'tab' key to adjust indentation. And the use parenthesis makes your code more readable.
if (car.xcor() + 10 == dog.xcor()) and (car.ycor() + 10 == dog.ycor()):
dog.clear()
else:
pass
I'm practicing python and one of the coding tasks assigned was to create a function that looks through a list and ignores numbers that occur between a 6 and a 9 and returns the sum of all other values.
Edit: this does not mean to add numbers whose values are less than 6 or greater than 9. It means to add all numbers of any value, but to ignore any numbers that come after a 6, until a 9 is seen. Symbolically if i means include and x means exclude, the code should return all the values marked as i:
[i,i...6, x,x,...,9,i,i...,6,x,x,...]
In other words, 6 turns off adding and if adding is off, 9 turns it back on.
Note that a 9 with no preceding 6 is just a number and will be added.
For example if I have a list:
[4,5,6,7,8,9,9]
the output should be:
8 <---(4+5+9)
The solution is provided but I'm having trouble understanding the code. I don't understand the purpose of the break statements in the code. The solution provided is as follows:
def summer_69(*arr):
total = 0
add = True
for num in arr:
while add == True:
if num!=6:
total = total + num
break
else:
add = False
while add == False:
if num !=9:
break
else:
add = True
break
return total
I'm really confused how the break statements help with the code. Particularly, I'm confused why the first 'break' is needed when there is already an 'else'.
The second break confuses me as well.
I understand that 'break' statements stop a loop and go onto the next loop.
My interpretation of the code so is 'if the number does not equal to 6 then total = total + num, if it does equal 6 then the loop is broken and if it is broken, add changes to False'.
I'm not sure if that interpretation is correct or not.
I was wondering how seasoned Python coders interpret 'breaks' vs 'else'.
break will exit whatever loop the statement is in. It's useful for many things, but often it's used to "short-circuit" the loop. If we know that the rest of the loop is irrelevant after some condition is met, then it's just wasted resources to keep looping through.
The break statement allow you to leave the while loop, but the if else statement allow you to stay in loop, until the condition of the while loop change or a break statement is in the action into the while loop
The solution you've provided is extremely convoluted and hard to understand.
A much better solution is:
total = 0
for num in arr_2:
if(num >= 6 and num <=9):
continue
total += num
Or a more pythonic way:
filtered_arr = filter(lambda x: x <6 or x > 9, arr_2)
total = reduce(lambda x, y: x + y, arr)
Anyways, in your solution, the first break is absolutely redundant. The reason why there is a break there, is because when you've found a number that doesn't equal 6, you add it, and you get out of the while loop.
In other words, the solution should have used an if statement, instead of the while statement. The break is there to basically have the while loop execute once.
Because, if a number does equal 6, then add will be false, and the while loop will terminate. If a number does not equal 6, you get out of the while loop. So the while loop is pointless, and meant to be an if statement instead.
This is a tricky way to handle program flow with a toggle nested in conditional loops.
It's a little hard to follow, but it is a well-known classic pattern.
Initially ADD == True, so if we start with a number that is not 6 (as in your example), the algorithm adds the number & breaks out of the first while loop. When it breaks, the next statement executed will be the line while add == False
At this point ADD == TRUE so the second while loop will not be entered. The next statement executed will be for num in arr (the outermost loop).
The outer FOR loop will go again and this process will repeat.
When you encounter a 6, the number will not be added and the break will not occur. The program will execute the else clause, setting ADD = FALSE.
After the else clause, execution continues with statement while add == false. Since ADD == FALSE at this point, the second while loop will be entered.
From now on ADD will be FALSE so the first While loop will not be entered and numbers will not be added. Instead, the condition for the second while loop will be evaluated for each number. As long as numbers are not equal to 9, the second while loop will not be entered.
When you encounter a 9, you will enter the second while loop, switch ADD back to TRUE, and break out of the while loop.
The first 9 comes after a 6 (ADD is FALSE) so it just toggles ADD from FALSE to TRUE and the number 9 doesn't get added.
When the NEXT 9 is encountered, ADD is TRUE and the number is not 6, so the first while loop will be entered and the number 9 will get added.
This is a classic pattern that used to be used in assembly language code perhaps 40 years ago. As written, the IF statements toggle a state variable. The state variable is turned on when the start condition is met, and turned off when a stop condition is met. The while loops ensure that the toggle can only be turned ON when it was OFF and vice versa, and provide places to put in different handling when the state is ON vs when it is OFF. This pattern brings certain efficiencies that are completely irrelevant in modern high-level languages.
There are better ways to do this in all modern languages, but as an exercise in following tricky program flow it's quite good :)
I'm currently writing a function to play Connect Four in Python3. I've progressed well through much of it but am having trouble alternating between two players.
What I'm trying to do is run a function that will place a chip in the appropriate location as a function of the current player, playturn(curr). So what I'm trying to say is that while there's no tie and while there's no winner, the game will continue and alternate between the two players.
If it's Player 1's turn, curr=1, and if it's Player 2's turn, curr=2.
My current code isn't working, as it won't allow me to switch between players after each turn if there's no tie or no winner. My logic here was that if curr=1 is initially 1, then I'll have to set curr=2 after the first move. Then, when curr=2, I have to switch curr equal back to 1. In the following code, checkforwinner and checkfortie are two functions that will return False if there is no winner and if there is no tie. playturn(curr) will place a chip in the correct column depending on the column chosen by either Player1 or Player2.
curr=1
while checkforwinner==False and checkfortie==False:
if curr==1:
curr==2
print(playturn(curr))
if curr==2:
curr==1
print(playturn(curr))
Can someone explain why this code is not working and what can be done to fix it?
curr==2 is a comparison. You probably want curr=2. The second if should be an elif.
There are a couple ways to make this nicer!
To make your original code work, you should use jspcal's recommendation to turn the comparison operators (==) to assignment operators (=).
You also need to use an elif for the second comparison, or every single loop will switch the player twice.
curr=1
while not (checkforwinner() or checkfortie()):
if curr==1:
curr=2
print(playturn(curr))
elif curr==2:
curr=1
print(playturn(curr))
You can also clean up the code a little:
def switch_player(current_player):
if current_player == 1:
return 2
elif current_player == 2:
return 1
while not (checkforwinner() or checkfortie()):
print(playerturn(curr))
curr = switch_player(curr)
The last version you might go with is the shortest, but is a little harder to read:
while not (checkforwinner() or checkfortie()):
print(playerturn(curr))
curr = 1 if curr == 2 else 2
If checkforwinner and checkfortie are functions, you need parenthesis after them:
while checkforwinner()==False and checkfortie()==False:
Also, as #jspcal pointed out, you want to assign values with a single '=' and only use '==' for boolean comparison.
Hey I'm writing a program that receives a broadcast from Scratch and then determines based on the broadcast, where to proceed. The code turns the broadcast(list item) into a string and then breaks that string into a list using .split(). The only problem is the broadcast may only be 1 word instead of 2. Is there a way to check if one of the list items from .split() is empty and then change it to a place holder value?
Where I am having trouble
scratchbroadcast = str(msg[1])
BroadcastList = scratchbroadcast.split()
#starts the switch statement that interprets the message and proceeds
#to the appropriate action
v = BroadcastList[0]
w = BroadcastList[1]
if BroadcastList[1] == '':
w = "na"
If BroadcastList contains only one word then BroadcastList will be a single-element list, e.g.
>>> "foo".split()
['foo']
Obviously we can't check whether the second item in the list is an empty string ''; there isn't a second element. Instead, check the length of the list:
w = "na" if len(BroadcastList) == 1 else BroadcastList[1]
Alternatively, use try to catch the IndexError (it's easier to ask for forgiveness than permission):
try:
w = BroadcastList[1]
except IndexError:
w = "na"
Okay, first consider this: how about the third item? Or the fourth? Or the forty-second?
If the string doesn't contain a splitter character (e.g. a space), you wouldn't end up with a list of two items, one of which blank -- you would end up with a list of only one item.
In Python, the length of something is generally obtained through the built-in len() function:
len([]) # == 0
len(["foo"]) # == 1
len(["foo", "bar"]) # == 2
Therefore, you would do:
if len(broadcast_list) == 1:
broadcast_list += [""]
Other ways of doing the same thing include broadcast_list.append("") and broadcast_list.extend([""]). Which one to use is completely up to you; += and .extend are more or less equivalent while .append can only add a single element.
Looking at the rest of your code, your case calls won't work like you expect them to: in Python, strings are truthy, so 'string' or 'otherString' is basically the same as True or True. or is strictly a boolean operator and you can't use it for 'either this or that'.
Python is notorious for not having a switch statement. Your attempt at implementing one would actually be kind of cute had you gone through with it -- something like that can be a pretty good exercise in Python OOP and passing functions as first-class objects. (In my day-to-day use of Python I hardly ever need to do something like that, but it's great to have it in your conceptual toolkit.)
You might be happy to learn that Python strings have a lower method; with it, your code would end up looking something like this:
v = broadcast_list[0].lower()
if v == 'pilight':
# ...
else if v == 'motor':
# ...
else if v == 'camera':
# ....
On a side note, you might want to have a look a PEP8 which is the de facto standard for formatting Python code. If you want other people to be able to quickly figure out your code, you should conform at least to its most basic propositions - such as classes being CamelCased and variables in lowercase, rather than the other way around.
I was wondering if someone can help me to fix the error my code for quick sort has:
It does not compile and highlights the last line of the code in red.
I can not figure out what is wrong. sort is already defined as a function so why is it highlighted as red?
def sort(*myarray):
less = []
equal = []
greater = []
if len(myarray) > 1:
pivot = myarray[0]
for x in myarray:
if x < pivot:
less.append(x)
if x == pivot:
equal.append(x)
if x > pivot:
greater.append(x)
return sort(less)+sort(equal)+sort(greater)
else:
return myarray
print sort([12,4,5,6,7,3,1,15])
You're defining the function as taking a variable number of arguments (the *myarray bit), but then using myarray inside as a single argument (the list to sort), when it is a list containing the list to sort.
You probably should remove the * from your function parameter. This questions esplains it quite thoroughly.
You could keep the *, but then you would have to play a bit with tuple unpacking to get the same result.
edit
Although the above is true, this might not be the issue you're encountering.
IDLE will give you the invalid syntax error on the ast line, because in interactive mode - with lines starting with >>>, it accepts only one statement at a time. In your case that statement is the sort() definition.
Try hitting enter 2 times after the function definition, this should get you back to the repl, where you can introduce another statement (print sort([12,4,5,6,7,3,1,15]))
There are a couple things wrong which makes me curious how you are testing this:
Python code is not "compiled", it is interpreted. (Okay, not precisely true; it's parsed into a sort of byte-code; still, it's not compiled in the same sense as a language such as C, where the entire program has to be converted into machine instructions before any of it can be run.) Also you mention the last line of code is highlighted in red -- by what?
This code actually works, but only if you remote the star/asterisk in front of myarray in def sort(*myarray):. Otherwise it actually returns a single-element tuple containing the original array.
Assuming you have two or more elements that equal a pivot at some point, you get an infinite loop, because you will get: equal = [x,x] (two elements at least), and then invoke sort([x,x]), which in its turn will take x as a pivot, and create equal = [x,x], and cause sort([x,x]), ....
Simple solution to this problem: What should be the output of the sort(equal)? How do you sort a list of identical elements?
Edit: Well, your comments show that you are looking for a different problem, but I'll leave it here because it explains a different issue you have with your code and should be solved.
If it is a function for quick sorting, can you really use the function sort in it?
Wouldn't something like this work?
def qsort(list):
pivind=0
left, right, pivot= [], [], []
for x in list:
if list[pivind]==x: pivot.append(x)
elif list[pivind]>x: left.append(x)
else: right.append(x)
if len(left)>1: left=qsort(left)
if len(right)>1: right=qsort(right)
return (left + pivot + right)