Putting an if-elif-else statement on one line? - python

I have read the links below, but it doesn't address my question.
Does Python have a ternary conditional operator? (the question is about condensing if-else statement to one line)
Is there an easier way of writing an if-elif-else statement so it fits on one line?
For example,
if expression1:
statement1
elif expression2:
statement2
else:
statement3
Or a real-world example:
if i > 100:
x = 2
elif i < 100:
x = 1
else:
x = 0
I just feel if the example above could be written the following way, it could look like more concise.
x = 2 if i>100 elif i<100 1 else 0 # [WRONG]

No, it's not possible (at least not with arbitrary statements), nor is it desirable. Fitting everything on one line would most likely violate PEP-8 where it is mandated that lines should not exceed 80 characters in length.
It's also against the Zen of Python: "Readability counts". (Type import this at the Python prompt to read the whole thing).
You can use a ternary expression in Python, but only for expressions, not for statements:
>>> a = "Hello" if foo() else "Goodbye"
Edit:
Your revised question now shows that the three statements are identical except for the value being assigned. In that case, a chained ternary operator does work, but I still think that it's less readable:
>>> i=100
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
0
>>> i=101
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
2
>>> i=99
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
1

If you only need different expressions for different cases then this may work for you:
expr1 if condition1 else expr2 if condition2 else expr
For example:
a = "neg" if b<0 else "pos" if b>0 else "zero"

Despite some other answers: YES it IS possible:
if expression1:
statement1
elif expression2:
statement2
else:
statement3
translates to the following one liner:
statement1 if expression1 else (statement2 if expression2 else statement3)
in fact you can nest those till infinity. Enjoy ;)

Just nest another if clause in the else statement. But that doesn't make it look any prettier.
>>> x=5
>>> x if x>0 else ("zero" if x==0 else "invalid value")
5
>>> x = 0
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'zero'
>>> x = -1
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'invalid value'

There's an alternative that's quite unreadable in my opinion but I'll share anyway just as a curiosity:
x = (i>100 and 2) or (i<100 and 1) or 0
More info here: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not

You can optionally actually use the get method of a dict:
x = {i<100: -1, -10<=i<=10: 0, i>100: 1}.get(True, 2)
You don't need the get method if one of the keys is guaranteed to evaluate to True:
x = {i<0: -1, i==0: 0, i>0: 1}[True]
At most one of the keys should ideally evaluate to True. If more than one key evaluates to True, the results could seem unpredictable.

yes you can by doing this :
i = int(input('type your num here : '))
x = 2 if i > 100 else ( 1 if i < 100 else 0)
print (x)

if i > 100:
x = 2
elif i < 100:
x = 1
else:
x = 0
If you want to use the above-mentioned code in one line, you can use the following:
x = 2 if i > 100 else 1 if i < 100 else 0
On doing so, x will be assigned 2 if i > 100, 1 if i < 100 and 0 if i = 100

The ternary operator is the best way to a concise expression. The syntax is variable = value_1 if condition else value_2. So, for your example, you must apply the ternary operator twice:
i = 23 # set any value for i
x = 2 if i > 100 else 1 if i < 100 else 0

Nested ternary operator is the best solution --
Example case -
4 = 1
3 = 2
2 = 3
1 = 4
a = 4
prio = 4 if a == 1 else (3 if a == 2 else (2 if a == 3 else 1))

People have already mentioned ternary expressions. Sometimes with a simple conditional assignment as your example, it is possible to use a mathematical expression to perform the conditional assignment. This may not make your code very readable, but it does get it on one fairly short line. Your example could be written like this:
x = 2*(i>100) | 1*(i<100)
The comparisons would be True or False, and when multiplying with numbers would then be either 1 or 0. One could use a + instead of an | in the middle.

It also depends on the nature of your expressions. The general advice on the other answers of "not doing it" is quite valid for generic statements and generic expressions.
But if all you need is a "dispatch" table, like, calling a different function depending on the value of a given option, you can put the functions to call inside a dictionary.
Something like:
def save():
...
def edit():
...
options = {"save": save, "edit": edit, "remove": lambda : "Not Implemented"}
option = get_input()
result = options[option]()
Instead of an if-else:
if option=="save":
save()
...

You can use nested ternary if statements.
# if-else ternary construct
country_code = 'USA'
is_USA = True if country_code == 'USA' else False
print('is_USA:', is_USA)
# if-elif-else ternary construct
# Create function to avoid repeating code.
def get_age_category_name(age):
age_category_name = 'Young' if age <= 40 else ('Middle Aged' if age > 40 and age <= 65 else 'Senior')
return age_category_name
print(get_age_category_name(25))
print(get_age_category_name(50))
print(get_age_category_name(75))

MESSAGELENGHT = 39
"A normal function call using if elif and else."
if MESSAGELENGHT == 16:
Datapacket = "word"
elif MESSAGELENGHT == 8:
Datapacket = 'byte'
else:
Datapacket = 'bit'
#similarly for a oneliner expresion:
Datapacket = "word" if MESSAGELENGHT == 16 else 'byte' if MESSAGELENGHT == 8 else 'bit'
print(Datapacket)
Thanks

Related

Why do these shorthands not work with each other?

I was wondering how to take advantage of shorthand notation of if-else and += in Python of this simple expression:
I tried to set brackets everywhere and changed += to *= which didn't change the situation of course.
This works as expected:
a, b = 0, True
for i in range(123):
if b == True:
a = a + 1
Still working as expected, trying shorthand of if-else led me to:
a, b = 0, True
for i in range(123):
a = a + 1 if b == True else a
Finally the attempt to write:
a, b = 0, True
for i in range(123):
a += 1 if b == True else a:
fails and surprisingly I get pretty quickly huge integers for a
Moreover I'd really like something more shorthanded, e.g.:
a, b = 0, True
for i in range(123):
a += 1 if b
The for-loop needs to stay as it is, since in my case there are other operations that affect b.
Since noone seems to be posting, why it goes like this, here is mine - lines:
a = a + 1 if b == True else a
a += 1 if b == True else a
are seen by python as:
a = (a + 1 if b == True else a)
a += (1 if b == True else a)
This is why you get large numbers fast in second version - you will add a to a, when b is False. If you want to keep the if, then go:
a += (1 if b else 0)
Also don't compare b to True (or False), go foif b`, as it's more pythonic (it will prevent some weird mistakes, when other code will start to interact with yours).
EDIT: go for #Tomerikoo answer for even shorter code, but keep in mind, that those waters can be muddy and not everyone knows / easily follows, that adding boolean to int treats first as 1 (or 0 if False).
To closest to your proal is probably:
a, b = 0, True
for i in range(123):
a += b
Since bool is a subtype of int, no conversion is necessary.
You can do:
for i in range(123):
if b:a+=1
You can also do:
for i in range(123):
a = a + 1*b
Because booleans are ints:
>>> isinstance(True, int)
True
>>> True == 1
True
just note that
a += x if condition else y
will resolve to a += x if the condition is True; otherwise it will be a += y. this is why your numbers get big...
apart from that i suggest you use what U10-Forward's answer suggests.

Linking up statements using the 'and' keyword [duplicate]

This question already has answers here:
Check if all values in list are greater than a certain number
(9 answers)
Closed 6 years ago.
I am doing this following:
if ycoords[0] > 0 and ycoords[1] > 0 and ycoords[2] > 0:
# do stuff
Can you shorten this code by doing something like:
if (ycoords[0] and ycoords[1] and ycoords[2]) > 0:
# do stuff
Yes, you could use all:
if all(x > 0 for x in ycoords):
or ycoords[:3] if ycoords has more than 3 elements.
No, you can however simply use min to simplify the test syntactically:
if min(ycoords[0],ycoords[1],ycoords[2]) > 0:
# do stuff
and given that ycoords exactly has three elements, even shorter:
if min(*ycoords) > 0:
#do stuff
you can here, as #Tagc says, omit the asterisk (*):
if min(ycoords) > 0:
#do stuff
but this will result in some overhead.
Another option is to use an all:
if all(x > 0 for x in [ycoords[0],ycoords[1],ycoords[2]]):
# do stuff
or again, if ycoords contains only these three elements:
if all(x > 0 for x in ycoords):
# do stuff
Something that is not intuitive is that and:
"neither and nor or restrict the value and type they return to False and True, but
rather return the last evaluated argument"
Just open a python terminal and do:
>> 4 and 3
3
Why is this important to take in account?
You might think that:
(ycoords[0] and ycoords[1] and ycoords[2]) > 0
is equivalent to:
ycoords[0] > 0 and ycoords[1] > 0 and ycoords[2] > 0
or that is equivalent to:
(bool(ycoords[0]) and bool(ycoords[1]) and bool(ycoords[2])) > 0
but it's instead equivalent to:
ycoords[2] > 0
So, be careful because the interpreter is not doing what you think is doing.

What does if-if-else one-line do in Python? [duplicate]

This question already has answers here:
Does Python have a ternary conditional operator?
(31 answers)
Closed 6 years ago.
I ran into this expression in a question here about knapsack problems:
def f(v, i, S):
if i >= len(v): return 1 if S == 0 else 0
count = f(v, i + 1, S)
count += f(v, i + 1, S - v[i])
return count
When I try to write out line two if i >= len(v): return 1 if S == 0 else 0 in a more general form I get an error:
In [3]: if test1 : print x if test2 else print y
File "<ipython-input-3-9d4131fa0c48>", line 1
if test1 : print x if test2 else print y
^
SyntaxError: Missing parentheses in call to 'print'
Here is a generalized form:
In [16]: if True : print("first") if True else print("second")
first
In [17]: if True : print("first") if False else print("second")
second
In [18]: if False : print("first") if True else print("second")
[nothing]
In [19]: if False : print("first") if False else print("second")
[nothing]
What do you call this?
I'm surprised you can just take out the second positive case for if...then...else and turn it into if...else.
UPDATE: Sorry bout the python3 noob mistake, I just wasn't paying attention. As noted, the answers don't make sense without the mistake, so I've striked out the erroneous code.
You have found the ternary operator, which is known as a Conditional Expression in Python. The expression x if condition else y means that if the condition (which can be a complex statement or function) evaluates to True, the expression returns x, and if the condition evaluates to False, the expression returns y.
It works like the following if-statement:
if test1:
if test2:
print(x)
else:
print(y)
Your error stems from not wrapping the print function arguments in a parentheses. This is a change made to Python 3, whereas in Python 2, your syntax would have been fine. Rewrite it to look like:
if test1: print(x if test2 else y)
and your error will go away.
I feel it is important to point out that what you describe (if-if-else) is not a conditional expression per se, but it does include one:
1 if S == 0 else 0 is a conditional expression
if i >= len(v): return 1 if S == 0 else 0 is a compound statement which comprises a simple if statement with a conditional expression.
So, if the first if evaluates to True, then the conditional expression will be evaluated and the appropriate element (in this case 1 or 0) returned to the preceding statement (return, here).
It is an if-expression: a if condition else b means: if condition is true, then the expression has value a, otherwise b
Your problem is unrelated, Seems you are using python 3, you got the example from python 2. In python 3 print is a function, so just add parentheses
if you are using python of version >3, then print should have parenthesis i.e ()

Putting a simple if-then-else statement on one line [duplicate]

This question already has answers here:
Does Python have a ternary conditional operator?
(31 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I'm just getting into Python and I really like the terseness of the syntax. However, is there an easier way of writing an if-then-else statement so it fits on one line?
For example:
if count == N:
count = 0
else:
count = N + 1
Is there a simpler way of writing this? I mean, in Objective-C I would write this as:
count = count == N ? 0 : count + 1;
Is there something similar for Python?
Update
I know that in this instance I can use count == (count + 1) % N.
I'm asking about the general syntax.
That's more specifically a ternary operator expression than an if-then, here's the python syntax
value_when_true if condition else value_when_false
Better Example: (thanks Mr. Burns)
'Yes' if fruit == 'Apple' else 'No'
Now with assignment and contrast with if syntax
fruit = 'Apple'
isApple = True if fruit == 'Apple' else False
vs
fruit = 'Apple'
isApple = False
if fruit == 'Apple' : isApple = True
Moreover, you can still use the "ordinary" if syntax and conflate it into one line with a colon.
if i > 3: print("We are done.")
or
field_plural = None
if field_plural is not None: print("insert into testtable(plural) '{0}'".format(field_plural))
count = 0 if count == N else N+1
- the ternary operator. Although I'd say your solution is more readable than this.
General ternary syntax:
value_true if <test> else value_false
Another way can be:
[value_false, value_true][<test>]
e.g:
count = [0,N+1][count==N]
This evaluates both branches before choosing one. To only evaluate the chosen branch:
[lambda: value_false, lambda: value_true][<test>]()
e.g.:
count = [lambda:0, lambda:N+1][count==N]()
<execute-test-successful-condition> if <test> else <execute-test-fail-condition>
with your code-snippet it would become,
count = 0 if count == N else N + 1

True and 'True' in python condition

If:
x = 0
b = x==0
and I print b it would print 'true'
but if I did:
x = 0
b = x ==3
and I printed b it would be false.
Instead of it printing false how would I take the boolean value b to print what text I wanted?
Let me explain further:
bool = all(n > 0 for n in list)
if bool != 'True':
print 'a value is not greater than zero'
But it prints nothing?
Something like this you mean?
x = 0
if x != 3:
print "x does not equal 3"
I think perhaps the following will help alleviate some of your confusion:
>>> 0==0
True
>>> 'True'
'True'
>>> (0==0) == 'True'
False
>>> (0==0) == True
True
An if statement as other answers suggest is a possibility (and you could add an else clause to print something specific in each case). More direct is an if/else operator:
print('equality' if b else 'diversity')
You could also use indexing, since False has the int value 0 and True the int value 1:
print(['different', 'the same'][b])
but I find that a bit less readable than the if variants.
Remove the quotes around True:
bool = all(n > 0 for n in list)
if bool != True:
print 'a value is not greater than zero'
or, you can also check for False:
bool = all(n > 0 for n in list)
if bool == False:
print 'a value is not greater than zero'
There are several other "shortcut" ways of writing it, but since you're a beginner let's not confuse the subject more than necessary.
>>> x = 0
>>> if not x == 3: print 'x does not equal 3'
x does not equal 3
lte me explain further:
>>> list = [-1, 1, 2, 3]
>>> if not all(n > 0 for n in list): print 'a value is not greater than zero'
a value is not greater than zero
# => or shorter ...
>>> if min(list) < 0: print 'a value is not greater than zero'
a value is not greater than zero
note that list is a builtin and shouldn't be used as a variable name.
>>> list
<type 'list'>
>>> list = [1, 2, "value not greater than 0"]
>>> list
[1, 2, "value not greater than 0"]
>>> del list
>>> list
<type 'list'>
...
a = lambda b :("not true","true")[b == 3]
print a(3)
will do it for you if you want to put it in a lambda.
You will need to do the printing yourself, as everyone suggested here.
It's worthy to note that some languages (e.g. Scala, Ruby, Groovy) have language features that enable you to write:
x should be(3)
And that will report:
0 should be 3 but is not.
In Groovy, with Spock testing framework, you can write:
def "my test":
when: x = 0
expect: x == 3
And that would output:
Condition not satisfied:
x == 3
| | |
0 | 3
false
I don't think this possibly cleanly in python though.
>>> 'True' is not True
True
'True' is a string
True is a boolean
They have nothing to do with each other, except coincidentally. The string value happens to have the same letters as the boolean literal. But that's just a coincidence.

Categories

Resources