I'm getting "invalid syntax" errors pointing to the "in" statement. What's my mistake?
while(notes > 1):
note = choice(scale)
if note[0].isupper() and not in patternNotes:
patternNotes.append(note)
notes -= 1
elif note is not rootNote and note not in patternNotes:
patternNotes.append(note)
notes -= 1
You probably want
if note[0].isupper() and note not in patternNotes:
rather than
if note[0].isupper() and not in patternNotes:
Note the lacking note in the second one.
It should be note[0].isupper() and note not in patternNotes: (notice the second note before not)
After that your syntax is fine:
i = {}
j = {}
print i is not j and j not in {}
# False
Note that this is an infinite loop under certain conditions, like "note in patternNotes". Move the "notes -= 1" statement outside the if/elif and the problem is solved.
Related
I am trying to use if-else expression which is supposed to break the loop if the if condition fails, but getting an invalid syntax error.
Sample code:
a = 5
while True:
print(a) if a > 0 else break
a-=1
Of course, if I write in the traditional way (not using the one liner) it works.
What is wrong in using the break command after the else keyword?
If I run this, I get the following error:
... print(a) if a > 0 else break
File "<stdin>", line 2
print(a) if a > 0 else break
^
SyntaxError: invalid syntax
This is because
print(a) if a > 5 else break
is a ternary operator. Ternary operators are no if statements. These work with syntax:
<expr1> if <expr2> else <expr3>
It is equivalent to a "virtual function":
def f():
if <expr2>:
return <expr1>
else:
return <expr3>
So that means the part next to the else should be an expression. break is not an expression, it is a statement. So Python does not expect that. You can not return a break.
In python-2.x, print was not a function either. So this would error with the print statement. In python-2.x print was a keyword.
You can rewrite your code to:
a = 5
while True:
if a > 5:
print(a)
else:
break
a -= 1
You can read more about this in the documentation and PEP-308.
If is an expression, break similar to return is a statement. You can't use two statements in a single sentence (unless you use a semicolon which is ugly). I know it would have been really cool if we can do that, but alas that's the way it is.
To put it in slightly simpler terms, you're misusing the 'one-line if statement' (ternary operator). It always evaluates to an expression (i.e., a value). That is,
<expr1> if <condition> else <expr2>
evaluates to <expr1> if <condition> is True, and to <expr2> if <condition> is False. This resulting value can then be used like any Python value, for example:
y = 0
x = (5 if (y > 0) else 6)
print(x) # 6
Of course, the parentheses are completely unnecessary (even discouraged), but hopefully are useful for understanding the meaning of that line.
Therefore,
print(a) if a > 0 else break
tries to evaluate print(a) (which, by the definition of print() in Python 3, always returns None – perfectly valid, but probably not what you usually want) and then break, which does not evaluate to anything because it is a statement (action), not an expression (value), hence the invalid syntax error.
Hence, if you want to execute one of two statements depending on a condition, you really need the multi-line solution proposed by
Willem Van Onsem. There may be hacky ways to do it in one line, but multiple lines is the usual solution for something like this in Python.
I made a function that consumes two dictionaries, curr_stats and weekly_result. If there are any keys in weekly_result that aren't in curr_stats, the function is supposed to just print invalid_msg, with no mutation of curr_stats.
But the if statement on the 5th line of my code doesn't seem to be working. It's supposed to trigger the next if statement, so no mutation of curr_stats occurs.
def update_standings(curr_stats, weekly_result):
invalid = 0
point_counter(weekly_result)
for team in weekly_result:
if team in curr_stats == False:
invalid = invalid + 1
if invalid > 0:
print(invalid_msg)
else:
for team in weekly_result:
curr_stats[team] = curr_stats[team] + weekly_result[team]
In Python, all comparisons have the same precedence, including in.
What's happening is comparison chaining, a special form intended to test transitive relationships like in math class:
if x_min < x < x_max:
...
As Paweł Kordowski pointed out in his comment, the above comparison chain is mostly equivalent to:
if x_min < x and x < x_max:
...
(There is one difference:
The "equivalent" code might evaluate x twice, while the comparison chain evaluates x exactly once.)
In your case, the comparison chain is:
if team in curr_stats == False:
...
...which is (mostly) equivalent to:
if team in curr_stats and curr_stats == False:
...
This is only true if curr_stats contains team and curr_stats is empty... which should never happen.
The problem with your code is the == False --- in part because it turned a comparison into a comparison chain, but mostly because you never needed it in the first place.
Python provides the not keyword for when you want a Boolean's opposite.
Your conditional statement should read:
if team not in curr_stats:
invalid = invalid + 1
One last suggestion:
This function can be made even shorter by getting rid of the invalid counter and just returning as soon as an invalid team is found.
(Once the you've discovered that weekly_result is invalid input, you probably don't care if it's "even more invalid".)
I also used dict.items to simplify the final for loop:
def update_standings(curr_stats, weekly_result):
point_counter(weekly_result)
for team in weekly_result:
if team not in curr_stats:
print(invalid_msg)
return
for team, result in weekly_result.items():
curr_stats[team] += result
I have written a very simple program in python
for i in range(1,1000):
if (i % 3 == 0) and (i % 5 == 0) :
result += i
else:
print('sum is {}'.format(result))
When I try to compile the problem I am getting the error.
NameError: name 'result' is not defined
This statement:
result += i
is equivalent to:
result = result + i
But, the first time this statement is reached in your loop, the variable result has not been defined, so the right-hand-side of that assignment statement does not evaluate.
Add result = 0 before your for loop.
First of all, your indentation is inconsistent and incorrect which makes it harder to read.
result = 0
for i in range(1,1000):
if (i % 3 == 0) and (i % 5 == 0) :
result += i
else:
print 'sum is ',result
This is the way to get around your error, but I don't think this is actually what you're trying to do. What is the problem you're trying to solve?
or...
try:
result += i
except:
result = i
but this won't get you past what happens if the loop condition never occurs (you would need another try in your printout), so just setting it prior to the loop is probably better.
If I have a function with multiple conditional statements where every branch gets executed returns from the function. Should I use multiple if statements, or if/elif/else? For example, say I have a function:
def example(x):
if x > 0:
return 'positive'
if x < 0:
return 'negative'
return 'zero'
Is it better to write:
def example(x):
if x > 0:
return 'positive'
elif x < 0:
return 'negative'
else:
return 'zero'
Both have the same outcome, but is one more efficient or considered more idiomatic than the other?
Edit:
A couple of people have said that in the first example both if statements are always evaluated, which doesn't seem to be the case to me
for example if I run the code:
l = [1,2,3]
def test(a):
if a > 0:
return a
if a > 2:
l.append(4)
test(5)
l will still equal [1,2,3]
I'll expand out my comment to an answer.
In the case that all cases return, these are indeed equivalent. What becomes important in choosing between them is then what is more readable.
Your latter example uses the elif structure to explicitly state that the cases are mutually exclusive, rather than relying on the fact they are implicitly from the returns. This makes that information more obvious, and therefore the code easier to read, and less prone to errors.
Say, for example, someone decides there is another case:
def example(x):
if x > 0:
return 'positive'
if x == -15:
print("special case!")
if x < 0:
return 'negative'
return 'zero'
Suddenly, there is a potential bug if the user intended that case to be mutually exclusive (obviously, this doesn't make much sense given the example, but potentially could in a more realistic case). This ambiguity is removed if elifs are used and the behaviour is made visible to the person adding code at the level they are likely to be looking at when they add it.
If I were to come across your first code example, I would probably assume that the choice to use ifs rather than elifs implied the cases were not mutually exclusive, and so things like changing the value of x might be used to change which ifs execute (obviously in this case the intention is obvious and mutually exclusive, but again, we are talking about less obvious cases - and consistency is good, so even in a simple example when it is obvious, it's best to stick to one way).
Check this out to understand the difference:
>>> a = 2
>>> if a > 1: a = a+1
...
>>> if a > 2: a = a+1
...
>>> a
4
versus
>>> a = 2
>>> if a > 1: a = a+1
... elif a > 2: a = a+1
...
>>> a
3
The first case is equivalent to two distinct if's with empty else statements (or imagine else: pass); in the second case elif is part of the first if statement.
In some cases, elif is required for correct semantics. This is the case when the conditions are not mutually exclusive:
if x == 0: result = 0
elif y == 0: result = None
else: result = x / y
In some cases it is efficient because the interpreter doesn't need to check all conditions, which is the case in your example. If x is negative then why do you check the positive case? An elif in this case also makes code more readable as it clearly shows only a single branch will be executed.
In general (e.g. your example), you would always use an if..elif ladder to explicitly show the conditions are mutually-exclusive. It prevents ambiguity, bugs etc.
The only reason I can think of that you might ever not use elif and use if instead would be if the actions from the body of the preceding if statement (or previous elif statements) might have changed the condition so as to potentially make it no longer mutually exclusive. So it's no longer really a ladder, just separate concatenated if(..elif..else) blocks. (Leave an empty line between the separate blocks, for good style, and to prevent someone accidentally thinking it should have been elif and 'fixing' it)
Here's a contrived example, just to prove the point:
if total_cost>=10:
if give_shopper_a_random_discount():
print 'You have won a discount'
total_cost -= discount
candidate_prime = True
if total_cost<10:
print 'Spend more than $10 to enter our draw for a random discount'
You can see it's possible to hit both conditions, if the first if-block applies the discount, so then we also execute the second, which prints a message which would be confusing since our original total had been >=10.
An elif here would prevent that scenario.
But there could be other scenarios where we want the second block to run, even for that scenario.
if total_cost<10:
<some other action we should always take regardless of original undiscounted total_cost>
In regards to the edit portion of your question when you said:
"A couple of people have said that in the first example both if statements are always evaluated, which doesn't seem to be the case to me"
And then you provided this example:
l = [1,2,3]
def test(a):
if a > 0:
return a
if a > 2:
l.append(4)
test(5)
Yes indeed the list l will still equal [1,2,3] in this case, ONLY because you're RETURNING the result of running the block, because the return statement leads to exiting the function, which would result in the same thing if you used elif with the return statement.
Now try to use the print statement instead of the return one, you'll see that the 2nd if statement will execute just fine, and that 4 will indeed be appended to the list l using append.
Well.. now what if the first ifstatement changes the value of whatever is being evaluated in the 2nd if statement?
And yes that's another situation. For instance, say you have a variable x and you used if statement to evaluate a block of code that actually changed the x value.
Now, if you use another if statement that evaluates the same variable x will be wrong since you're considering x value to be the same as its initial one, while in fact it was changed after the first if was executed. Therefore your code will be wrong.
It happens pretty often, and sometimes you even want it explicitly to be changed. If that's how you want your code to behave, then yes you should use multiple if's which does the job well. Otherwise stick to elif.
In my example, the 1st if block is executed and changed the value of x, which lead to have the 2nd if evaluates a different x (since its value was changed).
That's where elif comes in handy to prevent such thing from happening, which is the primary benefit of using it.
The other secondary good benefit of using elif instead of multiple if's is to avoid confusion and better code readability.
Consider this For someone looking for a easy way:
>>> a = ['fb.com', 'tw.com', 'cat.com']
>>> for i in a:
... if 'fb' in i:
... pass
... if 'tw' in i:
... pass
... else:
... print(i)
output:
fb.com
cat.com
And
>>> a = ['fb.com', 'tw.com', 'cat.com']
>>> for i in a:
... if 'fb' in i:
... pass
... elif 'tw' in i:
... pass
... else:
... print(i)
Output:
cat.com
'If' checks for the first condition then searches for the elif or else, whereas using elif, after if, it goes on checking for all the elif condition and lastly going to else.
elif is a bit more efficient, and it's quite logical: with ifs the program has to evaluate each logical expression every time. In elifs though, it's not always so. However, in your example, this improvement would be very, very small, probably unnoticeable, as evaluating x > 0 is one of the cheapest operations.
When working with elifs it's also a good idea to think about the best order. Consider this example:
if (x-3)**3+(x+1)**2-6*x+4 > 0:
#do something 1
elif x < 0:
#do something 2
Here the program will have to evaluate the ugly expression every time! However, if we change the order:
if x < 0:
#do something 2
elif (x-3)**3+(x+1)**2-6*x+4 > 0:
#do something 1
Now the program will first check if x < 0 (cheap and simple) and only if it isn't, will it evaluate the more complicated expression (btw, this code doesn't make much sense, it's just a random example)
Also, what perreal said.
Can I do something like this in Python?
for (i = 0; i < 10; i++):
if someCondition:
i+=1
print i
I need to be able to skip some values based on a condition
EDIT: All the solutions so far suggest pruning the initial range in one way or another, based on an already known condition. This is not useful for me, so let me explain what I want to do.
I want to manually (i.e. no getopt) parse some cmd line args, where each 'keyword' has a certain number of parameters, something like this:
for i in range(0,len(argv)):
arg = argv[i]
if arg == '--flag1':
opt1 = argv[i+1]
i+=1
continue
if arg == '--anotherFlag':
optX = argv[i+1]
optY = argv[i+2]
optZ = argv[i+3]
i+=3
continue
...
Yes, this is how I would do it
>>> for i in xrange(0, 10):
... if i == 4:
... continue
... print i,
...
0 1 2 3 5 6 7 8 9
EDIT
Based on the update to your original question... I would suggest you take a look at optparse
for (i = 0; i < 10; i++)
if someCondition:
i+=1
print i
In python would be written as
i = 0
while i < 10
if someCondition
i += 1
print i
i += 1
there you go, that is how to write a c for loop in python.
There are two things you could do to solve your problem:
require comma-separated arguments which are going to be grouped into the following option value, you could use getopt, or any other module then.
or do more fragile own processing:
sys.argv.pop()
cmd = {}
while sys.argv:
arg = sys.argv.pop(0)
if arg == '--arg1':
cmd[arg] = sys.argv.pop(0), sys.argv.pop(0)
elif:
pass
print(cmd)
Strange way:
for x in (x for x in xrange(10) if someCondition):
print str(x)
You should use continue to skip a value, in both C and Python.
for i in range(10):
if someCondition:
continue
print(i)
You probably don't actually need the indices, you probably need the actual items. A better solution would probably be like this:
sequence = 'whatever'
for item in sequence:
if some_condition:
continue
do_stuff_with(item)
You could first turn the argv list into a generator:
def g(my_list):
for item in my_list:
yield item
You could then step through the items, invoking the generator as required:
my_gen = g(sys.argv[1:]):
while True:
try:
arg = my_gen.next()
if arg == "--flag1":
optX = my_gen.next()
opyY = my_gen.next()
--do something
elif arg == "--flag2":
optX = my_gen.next()
optY = my_gen.next()
optZ = my_gen.next()
--do something else
...
except StopIteration:
break
You can ensure that an index is incremented within a try...finally block. This solve the common problem of wanting to continue to the next index without having to copy/past i += 1 everywhere. Which is one of the main advantages the C-like for loop offers.
The main disadvantage to using a try...finally is having to indent your code once more. but if you have a while loop with many continue conditions its probably worth it.
Example
This example demonstrates that i still gets incremented in the finally block, even with continue being called. If i is not incremented its value will remain even forever, and the while loop will become infinite.
i = 0
while i < 10:
try:
print(i)
if i % 2 == 0:
continue
finally:
i += 1
without it you would have to increment i just before calling continue.
i = 0
while i < 10:
print(i)
if i % 2 == 0:
i += 1 # duplicate code
continue
i += 1
for i in xrange(0, 10):
if i % 3 == 0
continue
print i
Will only values which aren't divisible by 3.
If you need to iterate over something, and need an index, use enumerate()
for i, arg in enumerate(argv):
...
which does the same as the questioner's
for i in range(0,len(argv)):
arg = argv[i]
Your problem seems to be that you should loop not raw parameters but parsed parameters. I would suggest you to consider to change your decision not to use standard module (like the others).
increament = 4 #say
for i in range(n):
#write your code here
n=n+increment
this might be the simple solution to the problem if you just want to iterate through the array by skipping 4 members