TL;DR: The ternary operator in Python is written in the form:
resultado_pro_caso_verdadeito if condicao else resultado_pro_caso_falso
With the keywords if...else
separating the 3 terms.
In Python, things are different from language that inherits direct syntax from C, such as Java, Javascript and others.
First, until Python 3.7 (the most current version), assignment actions are exclusively commands (statments), and cannot be used as part of an expression. (From Python 3.8 this will be possible with the use of the operator :=
)
In addition, the ternary operator that exists in C-like languages: expr? res_true: res_false
item a different syntax in Python - it uses a if...else
online as in res_true if expr else res_false
.
Then his expression
(seventh_state = False, seventh_state = True)[state_machine_var == 7]
should be written, if necessary, as:
seventh_state = True if state_machine_var == 7 else False
Only in this case you don’t even need it - since the expression itself state_machine_var == 7
already has boolean result True
or False
, then you just really need to:
seventh_state = state_machinne_var == 7
Historical and other forms
The syntax for ternary operators expr1 if condition else expr2
was only implemented in version 2.5 of Python, which is from 2006. Before that people used recipes like the one in the question to try to have the same functionality. The official recommendation, however, was to create a set of if/else
with even separate blocks.
The first recipe for ternary operators in old Python, which can still be found in many tutorials and books Python 2 took advantage of a characteristic of operators and
and or
python - and would suggest using the following form: cond and expr1 or expr2
The idea in that way is as follows:
An expression with and
only has "True" value if your two operands are positive. Then the language shortcuts: if you have expr3 and expr4
and expr3
is false, the code of expr4
is never executed. In addition to the shortcut, there is a feature - the whole value of expr3 and expr4
if expr3 is true, it is expr4
- the and
does not test expr4 - no matter if its value is a "true" or "false" object, as it was only executed respecting the and
its value is the final value of the and
.
Already the or
is the opposite - the language shortcut is: if in expr5 or expr6
, expr5
has a true value, its output is used as the whole expression value and expr6
is never executed.
The precedence of and
is greater than the precedence of or
, then cond and expr1 or expr2
is the same as (cond and expr1) or expr2
thus, in cond and expr1 or expr2
the operator and
will always perform the expr1
only if the expression given in cond
is true. And then you will get as a result, instead of "True/False" the result of expr1
. The operator or
, in turn, if this first working of it is true, it assumes the value of that working, and if it is false, the second working - expr2
is evaluated and used as a result of the whole expression.
The big problem this way is that if the value of expr1
has a false boolean value in Python, expr2 will be used anyway - even if the condition is true. And in Python, None objects, any number with value 0 (int, float, Complex, Fraction, Decimal or other type of custom number), any sequence, map or empty container ("", [] set(), {}) are objects with false boolean value.
The second fear is like the one that appears in the question here: create a sequence with the desired result expressions, and use the condition as the index of this sequence - using the fact that in Python, the booleans True and False also have numerical values 1 and 0, respectively:
[expr2, expr1][cond]
It has two disadvantages: one that the order of the desired expressions is reversed - that is, when cond is True, Python takes the value at index 1 of the sequence, which is the second. The other is that no matter the condition, the expr2
and expr1
are always executed - if they involve a function call that uses resources, gets bad, or worse, or accounts with values that are not available if cond
is false, nor is it possible to write the expression in this way.
Future
As of Python 3.8 (currently in Beta, scheduled for the end of October 2019), the assignments in expressions with the operator :=
will become valid, and this greatly increases the utility of the ternary operator - since it is possible to re-use a value calculated during the condition.
So if you need a "face" function call and then run code depending on the result of that call, but using the return value, until today (Python 3.7), the only way to do that is:
valor_intermediario = funcao_cara()
if valor_intermediario > 5:
resultado = coeficiente_grande * valor_intermediario
else:
resultado = coeficiente_pequeno * valor intermediaio
With the new type of assignment this sequence can be written like this:
resultado = coeficiente_grande * interm if (interm:= funcao_cara()) > 5 else coeficiente_pequeno * interm
We are at [pt.so], so please ask your question in our language. Take the opportunity to do the [tour], read the [Ask] guide and access [help].
– Woss
What do you want to do? This code makes no sense. Use and translate to Portuguese.
– Maniero
Do you want to
seventh_state
be itFalse
whenstate_machine_var
is different from 7 andTrue
when it’s the same, then why don’t you justseventh_state = (state_machine_var == 7)
? Much simpler, easier to read and understand and has valid syntax.– Woss
This code is a simplification of the original code, it is normal not to make much sense out of context. I thank @Andersoncarloswoss ! But it doesn’t answer my question
– FMAPR
Incidentally, in the previous line,
loop x in range(0, 10)
, thatloop
does not exist in Python, maybe the syntax error starts there. Possibly it would befor
correct by adding the two dots to the end of the line.– Woss
I’ve fixed @Andersoncarloswoss but the error was passing here, the loop is correct
– FMAPR