In some languages (I think php and Java) you can omit the second part of the ternary operator as such:
a = "This is a string"
result = a ? : False
The above should be equivalent to
a = "This is a string"
result = a ? a : False
I want to shorten the ternary operator in the following (simplified) python code:
def myFunc():
return "This string could be empty, but now it's not."
result = myFunc() if myFunc() else False
print(result)
This will print the string if it's not empty, but print False when it is empty.
The reason why I want it shorter is because now, I have to call myFunc() two times instead of just once if you were able to omit one of them as is possible in other languages.
Of course I could just assign myFunc() to a variable and use the variable twice in the ternary operator but this would make it bigger again.
Is there any easy way to do this in python? Or is this just not possible?
You can use or here as an empty string evaluates as a Falsey value:
result = myFunc() or False
Refer to Truth Value Testing
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.
Is there method by using python if/else (ternary_operator) to achieve this function:
flag = True # or False
if flag:
print 'abc'
else:
pass
I tried to using:
print 'abc' if flag else ''
But a blank line will be print if the flag == False. Because:
print 'abc' if flag else '' == print ('abc' if flag else '')
Is there any way can make print nothing if flag == False without using ;?
Thanks in advance.
By the way, I'v tried using lambda, but it wasn't successful, here my code:
a = lambda x: x if False else None
print a(1)
Result:
>> python a.py
None
In Python 2.X print is a statement while in 3.X print is a function.
You can do from __future__ import print_function and print will now be a function. You can then do print("abc") if condition else None if you want to print in an expression. Note that the value of the expression is always None, but it may or may not print "abc" depending on the value of condition.
You may want to reconsider your programming style. It can be confusing with side-effects, like printing, happening in expressions. Furthermore, Python isn't ideal for functional programming, in my opinion, for a number of reasons. For example:
There are no proper tail calls so you would easily get stack overflows (or max recursion depth errors).
You cannot have statements in lambda-expressions. This includes yield statements that otherwise could be used to mitigate the lack of tail calls.
Why not just:
if flag:
print "abc"
else:
# do something else
?
from __future__ import print_function
print('abc') if flag else None
Assignment:
Return the number of occurrences of character c in string s,
ignoring case. Use loops. Do not use the in-built string method count,
which does a similar thing. The idea is to learn to write loops. You
should ignore case when comparing a character of s with c.
My attempt:
def countletter(s, c): #BAD
count = 0
for c in s:
if c == c:
count += 1
return count
Am I on the right track? I seem to get some assertion errors when I test it in the main...
your return is at wrong place. So your function is actually returning only after one iteration.
Also you should not use the variable name c in for loop, use some different variable, as it replaces the value of c recieved from the function call with the current character being fetched by the for-loop.
def countletter(s, c): #BAD
count = 0
for x in s:
if x.lower() == c.lower():
count += 1
return count
print countletter("abcdefFf","F") #prints 3
print countletter("a","A") #prints 1
In addition to the answers above, there is a built-in method count in Python. You can use it in your project, if this function isn't a homework etc.(Oh, i saw now, it is an homework. But additional information is harmless.:) )
"baris".count("b")
returns 1
If you compare the variable c defined by for c in s: you are always going to get true. So, your comparison should look like c == 'c' (you can figure out how to do the case insensitive check) and your return is indented incorrectly
The position of the return statement is wrong. Delete the four spaces (or a tab what you've used)
Just as another example of a way to do this outside of the built-in count() method, one can use a generator expression and the sum() builtin:
>>> def countletter(s, c):
... return sum(x.lower() == c.lower() for x in s)
...
>>> countletter("abcdefFf", "F")
3
>>> countletter("a", "A")
1
What we do is produce a generator of True and Falses (True where the character matches). sum() will then give us the count, as True is 1 in Python, and False is 0:
>>> True == 1
True
>>> False == 0
True
From what I have read, I found that a built-in ternary operator does not exist (I will be happy to know more about it.).
I found the following code as a substitute:
def val():
var = float(raw_input("Age:"))
status = ("Working","Retired")[var>65]
print "You should be:",status
I couldn't understand how this code works; can anyone explain me how actually the code is working? I am also interested to know why the ternary operator doesn't exist; any references or links about this will be ore useful.
I'm running Python 2.6.4 on Windows Vista.
Python has a construct that is sort of like the ternary operator in C, et al. It works something like this:
my_var = "Retired" if age > 65 else "Working"
and is equivalent to this C code:
my_var = age > 65 ? "Retired" : "Working";
As for how the code you posted works, let's step through it:
("Working","Retired")
creates a 2-tuple (an immutable list) with the element "Working" at index 0, and "Retired" at index 1.
var>65
returns True if var is greater than 65, False if not. When applied to an index, it is converted into 1 (True) or 0 (False). Thus, this boolean value provides an index into the tuple created on the same line.
Why hasn't Python always had a ternary operator? The simple answer is that Guido van Rossum, the author of Python, didn't like/didn't want it, apparently believing that it was an unnecessary construct that could lead to confusing code (and anyone who's seen massively-nested ternary operators in C can probably agree). But for Python 2.5, he relented and added the grammar seen above.
Python (2.5 and above) does indeed have a syntax for what you are looking for:
x = foo if condition else bar
If condition is True, x will be set to foo, otherwise it will be set to bar.
Examples:
>>> age = 68
>>> x = 'Retired' if age > 65 else 'Working'
>>> x
'Retired'
>>> age = 35
>>> y = 'Retired' if age > 65 else 'Working'
>>> y
'Working'
because True casts to 1 and False casts to 0 so if var = 70
("Working","Retired")[var>65]
becomes
("Working", "Retired")[1]
a nice little shortcut ... but I find it can be a little confusing with anything but a simple condition, so I would go with TM's suggestion
"Retired" if var > 65 else "Working"
indexing into a list
The use of
[expression_when_false, expression_when_true][condition] # or
(expression_when_false, expression_when_true)[condition]
takes advantage of the fact that in Python True equals (but isn't!) 1 and False equals (but isn't!) 0. The expression above constructs a list of two elements, and uses the result of condition to index in the list and return only one expression. The drawback of this method is that both expressions are evaluated.
and-or shortcuts
Since the creation of Python, there was a form of this operation:
condition and expression_when_true or expression_when_false
This takes a shortcut and evaluates only one expression, but has a bug-prone drawback: the expression_when_true must not evaluate to a non-true value, otherwise the result is expression_when_false. and and or are "short-circuiting" in Python, and the following rules apply:
a and b #→ a if a is false, else b
a or b #→ a if a is true, else b
If condition is false, then expression_when_true is never evaluated and the result is expression_when_false. OTOH, if condition is true, then the result is the result of (expression_when_true or expression_when_false); consult the table above.
ternary conditional operator
Of course, since Python 2.5, there is a ternary conditional operator:
expression_when_true if condition else expression_when_false
The strange (if you are accustomed to the C-like ternary conditional operator) order of the operands is attributed to many things; the general intention is that condition should be true most of the time, so that the most common output comes first and is most visible.
Short-circuit boolean expressions
There is also an option to short-circuit logical operations:
>>> (2+2 == 4) and "Yes" or "No"
'Yes'
>>> (2+2 == 5) and "Yes" or "No"
'No'
In your example:
>>> (int(raw_input("Age: ")) > 65) and "Retired" or "Working"
Age: 20
'Working'
>>> (int(raw_input("Age: ")) > 65) and "Retired" or "Working"
Age: 70
'Retired'
Read more about this technique in Charming Python: Functional Programming in Python, Part 1.
in the code that you posted the following line is emulating ternary:
status = ("Working","Retired")[var>65]
here tuple ("Working","Retired") accessed with an index [var>65] which evaluates to either True (1) or False (0). When it's accessed with index 0, status will be 'Working'; if index is 1 then it'll be ``Retired'`. It's a fairly obscure way to do conditional assignment, use the normal ternary syntax that was introduced in py2.5 as was said.
There was originally no ternary operator because "Explicit is better than implicit", and it was seen as unpythonic. I don't like python's ternary op too much, either, but it exists:
x = foo if condition else bar
as shown by TM.
As for status = ("Working","Retired")[var>65],
var > 65 returns a boolean value: either True or False; however, Python treats boolean types quite weakly: True is 1 and False is 0 in some contexts. You can check it out by doing >>> True == 1.
status = ("Working","Retired")[var>65]
This line works as a ternary operator because the expression var>65 returns 1 or 0, depending on whether var is bigger than 65 or not. So if var>65, then the line becomes this:
status = ("Working","Retired")[1]
that is, the second element of the sequence ("Working","Retired"). It looks odd but not if you write it like this instead:
status_sequence = ("Working","Retired")
status = status_sequence[1]
so status = "Retired".
Similarly, if var<=65 then it becomes
status = ("Working","Retired")[0]
and status = "Working".
Only the "status =" line of that code implements something like the ternary operator.
status = ("Working","Retired")[var>65]
This creates a two-element tuple, with strings 'Working' at index 0, and 'Retired' at index 1. Following this, it indexes into that tuple to pick one of the two items, using the results of the expression var > 65.
This expression will return True (equivalent to 1, thus picking 'Retired') if the value of var is greater than 65. Otherwise it will return False (equivalent to 0, thus picking 'Working').
There is a key difference between this approach and the ternary operator, however, although it doesn't matter in your particular example. With the tuple-indexing approach, both values are evaluated but only one is returned. With the ternary operator, only one of the two values is actually evaluated; this is referred to as "short-circuit" behaviour. It can matter in cases like this:
status = funcA() if var > 65 else funcB()
status = (funcB(), funcA())[var > 65]
In the first case, either funcA() is called or funcB() is called, but never both. In the latter case, both are called first, and the results are stored in the tuple -- then only one is picked and the tuple is discarded.
This is especially important to understand if either funcA() or funcB() have "side-effects", meaning they change other data as they execute.
In Python 2.6 and up:
print "You should be {0}.".format("retired" if var>65 else "working")
In Python 3.1 and up:
print ("You should be {}.".format("retired" if var>65 else "working"))
this is the form with the python ternary operator
def val():
var = float(raw_input("Age:"))
status = "Retired" if var > 65 else "Working"
print "You should be:",status
the code you showed is a bit tricky: it creates a two elements tuple whose elements are at position 0 and 1. to select the right element it uses a condition which return a boolean but booleans in python are integers so you can use it as special indexes (they can be either 0 or 1).
trying to give a complete answer based on the answers given here.
the way you found (please don't use this one because it is not very readable):
def val():
var = float(raw_input("Age:"))
status = ("Working","Retired")[var>65]
print "You should be:",status
using the python 2.5+ syntax:
def val():
var = float(raw_input("Age:"))
status = "Working" if var>65 else "Retired"
print "You should be:",status
using the other common method still preferred by some people:
def val():
var = float(raw_input("Age:"))
status = var>65 and "Working" or "Retired"
print "You should be:",status
i personally tend to use the last since the order of the operands is the same as the C ternary operator.
EDIT:
found some problems with the last approach (thx Roberto Bonvallet).
from wikipedia:
this code would break if op1 could be
a "falsy" value (None, False, 0, an
empty sequence or collection, …) as
the expression would return op2
(whether it was truthy or falsy)
instead of the (falsy) op1
so my final suggestion would be to use the 2.5+ ternary operator since it is simple, readable and offers short-circuit behavior.