The syntax a if b else c is a ternary operator in Python that evaluates to a if the condition b is true - otherwise, it evaluates to c. It can be used in comprehension statements:
>>> [a if a else 2 for a in [0,1,0,3]]
[2, 1, 2, 3]
So for your example,
table = ''.join(chr(index) if index in ords_to_keep else replace_with
for index in xrange(15))
Answer from Amber on Stack OverflowQuestion About ternary and list comprehension. I can't seem to find a definite answer as the documentation is confusing. Can one use a statement (like a function call) in either of these or it just limited to expressions? Thanks in advance.
Videos
The syntax a if b else c is a ternary operator in Python that evaluates to a if the condition b is true - otherwise, it evaluates to c. It can be used in comprehension statements:
>>> [a if a else 2 for a in [0,1,0,3]]
[2, 1, 2, 3]
So for your example,
table = ''.join(chr(index) if index in ords_to_keep else replace_with
for index in xrange(15))
To use the else in list comprehensions in python programming you can try out the below snippet. This would resolve your problem, the snippet is tested on python 2.7 and python 3.5.
obj = ["Even" if i%2==0 else "Odd" for i in range(10)]
- If you mean to write list comprehension you missed
[,]: - There is no
is not inoperator. Usenot in. typefunction does not returnstring. Why not useisinstance(item, int)?
[lst.append(dict2obj(item)) if not isinstance(item, int) else lst.append(item)
for item in v]
Use simple for loop if possible. It's more readable.
for item in v:
if not isinstance(item, int)
lst.append(dict2obj(item))
else:
lst.append(item)
If the lst is empty from the start, you can simply create it like this:
lst = [dict2obj(item) if not isinstance(item, int) else item for item in v]
If you already have the list and want to add items, the proper way to do this in Python is to just extend the list you have with the new list:
lst.extend([dict2obj(item) if not isinstance(item, int) else item for item in v])
Or something like this (this uses an generator) to prevent extra overhead:
map(lst.append, (dict2obj(item) if not isinstance(item, int) else item for item in v))
Your "practical example" is written as:
>>> strList = ['Ulis', 'Tolus', 'Utah', 'Ralf', 'Chair']
>>> sum(1 for el in strList if el.startswith('U'))
2
Your other example (if I understand correctly) is:
>>> list1 = [4, 6, 7, 3, 4, 5, 3, 4]
>>> list1.count(4)
3
(or just adapt the strList example, but nothing wrong with using builtin methods)
@Jon Clements gave you an excellent answer: how to solve the problem using Python idiom. If other Python programmers look at his code, they will understand it immediately. It's just the right way to do it using Python.
To answer your actual question: no, that does not work. The ternary operator has this form:
expr1 if condition else expr2
condition must be something that evaluates to a bool. The ternary expression picks one of expr1 and expr2 and that's it.
When I tried an expression like c += 1 if condition else 0 I was surprised it worked, and noted that in the first version of this answer. @TokenMacGuy pointed out that what was really happening was:
c += (1 if condition else 0)
So you can't ever do what you were trying to do, even if you put in a proper condition instead of some sort of loop. The above case would work, but something like this would fail:
c += 1 if condition else x += 2 # syntax error on x += 2
This is because Python does not consider an assignment statement to be an expression.
You can't make this common mistake:
if x = 3: # syntax error! Cannot put assignment statement here
print("x: {}".format(x))
Here the programmer likely wanted x == 3 to test the value, but typed x = 3. Python protects from this mistake by not considering an assignment to be an expression.
You can't do it by mistake, and you can't do it on purpose either.
You don't need any conditional expression* here, as str.split() always returns a list, even if only containing one word:
lst[:] = [word for words in lst for word in words.split()]
Demo:
>>> lst = ['word','word','multiple words','word']
>>> [word for words in lst for word in words.split()]
['word', 'word', 'multiple', 'words', 'word']
The conditional expression can be used wherever you could use a simple expression in the syntax; that means anywhere it says expression or old_expression in the list display grammar:
list_display ::= "[" [expression_list | list_comprehension] "]"
list_comprehension ::= expression list_for
list_for ::= "for" target_list "in" old_expression_list [list_iter]
old_expression_list ::= old_expression [("," old_expression)+ [","]]
old_expression ::= or_test | old_lambda_expr
list_iter ::= list_for | list_if
list_if ::= "if" old_expression [list_iter]
So the first part of a list comprehension, but also the part that produces the outermost iterator (evaluated once), the if expressions, or any of the nested iterators (evaluated each iteration of the next outer for loop).
*It's called the conditional expression; it is a ternary operator, but so is the SQL BETWEEN operator.
First of all, you have the order wrong. To use the ternary operator, you have to do it like this:
[a if c else b for item in list]
That being said, you cannot really have another list comprehension level embedded depending on some condition. The number of levels has to be fixed.
As you are just looking to split for whitespace, you can just perform this anyway though, as splitting a string without whitespace will still give you back a list with a single item back:
[subword for word in list for subword in word.split()]
I am trying to get my head around the syntax for list comprehensions.
My code below returns a list with the positions of the letter 's' in the string variable.
string = 'This is a sentence' search = 's' # this returns a list with [3,6,10] result = [i for i, ch in enumerate(string) if ch ==search)]
result = [3, 6, 10]
If I wanted to return only the even positions, I would do:
result = [i for i, ch in enumerate(string) if ch ==search) and i%2==0]
result = [6, 10]
I notice that if the conditional comes at the start, then it has to have an else statement. Is that right? Is this to force a value whereas the example above just returns a filtered result?
e.g.:
result = [i if i%2 == 0 else None for i, ch in enumerate(string) if ch ==search)]
result = [None, 6, 10]
Am I understanding this correctly?