in OR condition which side evaluate first in python? - python

if cpu_expensive_condition() or simple_condition():
do_something()
out of two condition in OR statement in above python code which will be evaluate first ? , and is it compulsory that both will be evaluate ?

The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Quoted from Python Language Reference

Python evaluates from left to right, and both sides do not need to be evaluated. Consider the following example.
def left(x):
print 'left'
return x
def right(x):
print 'right'
return x
if left(False) or right(False):
print 'Done'
if left(True) or right(True):
print 'Done'
This will produce the following output:
left
right #This is where the first if statement ends.
left
Done #Only the left side was evaluated

According to Boolean Operations — and, or, not in the Python documentation:
This is a short-circuit operator, so it only evaluates the second argument if the first one is False.
So cpu_expensive_condition() will always be evaluated. simple_condition() will only be evaluated when cpu_expensive_condition() returns False (or something that evaluates to False, such as 0 or '' or None).
See also: Does Python support short-circuiting?

Python does short-circuit evaluation. Of course the first statement will be evaluated first. The second will only be evaluated if the first is False or false-ish.

Related

Python checking if a variable is true without the == operator

I have recently stumbled upon this bit of code:
def equal_button_press(self):
if self.add_trigger or self.sub_trigger or self.mult_trigger or self.div_trigger or self.asin_trigger:
In the if statement there is no specification for the code to check whether any of the variables self.add_trigger, self.sub_trigger, self.mult_trigger, self.div_trigger or self.asin_trigger are true.
Does this mean that it is possible to check if the object is true without the == operator?
The == operator compares the value or equality of two objects, not if they are True. If the 2 objects are equal, then python will return True.
Here's a pretty great article going in depth about this: https://towardsdatascience.com/comparison-in-python-is-not-as-simple-as-you-may-think-a83eec69ab54
That being said, there are truthy and falsy values in Python:
Values that evaluate to False are considered Falsy.
Values that evaluate to True are considered Truthy.
Some truthy values include:
Non-empty sequences or collections
Numeric values that are not zero.
Some falsy values include:
Zero of any numeric type.
Empty sequences or collections
None and False
So the code is checking which values are truthy, and those values will be outputted.
With the Boolean OR operator, you can connect two Boolean expressions into one compound expression. At least one subexpressions must be true for the compound expression to be considered true, and it doesn’t matter which. If both subexpressions are false, then the expression is false.
The clause inside of an if statement to determine whether it will be executed or not is not specifically only done when a value is equal to true (In Python, True) but can also be triggered if the variable or logical statement returns any value that is not 'falsy'.
#sj95126 provided the exact answer in the comments that I was also going to recommend on this!
Documentation Reference: https://docs.python.org/3/library/stdtypes.html#truth-value-testing
Yes, it is possible to check if a value is True without the == operator. An if statement takes a boolean after the if keyword. The == operator checks if the 2 values on both sides are the same. If they are, it "returns" True. Otherwise, it "returns" False.
foo = True
# These if statments are the same
if foo == True:
print("foo is True")
if foo:
print("foo is True")

How to use parentheses correctly?

Why does it work differently?
p='/content/Images_of_Waste/img/PET968.txt'
p[-3:]!='txt' and p[-3:]!='jpg'
False
p[-3:]!=('txt' and 'jpg')
True
How can I use parentheses correctly?
In Python, non-empty strings are effectively True.
That is to say,
if 'txt':
# this code will execute
As the #gimix mentions below, however,
if 'txt' == True:
# this code will not execute
In terms of ('txt' and 'jpg'), 'txt' is not False, and neither is 'jpg', thus, ('txt' and 'jpg') evaluates to 'jpg' per #Manish's comment.
if p[-3:] not in ('txt', 'jpg'):
# Do stuff
p='/content/Images_of_Waste/img/PET968.txt'
p[-3:]!='txt' and p[-3:]!='jpg'
An important point to note: (from the docs)
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
In here, p[-3:] gives txt. When you compare it to p[-3:]!='txt' and p[-3:]!='jpg', the first condition returns False as p[-3:] is indeed txt. And according to the documentation, if x evaluated to False, its value is returned. So you get False
Another point to note in operator precedence (from the docs)
You can see in the operator precedence that the following is evaluated first:
Binding or parenthesized expression, list display, dictionary display, set display.
The expression enclosed in brackets are given the first precedence and are evaluated first.
p[-3:]!=('txt' and 'jpg')
In this case, ('txt' and 'jpg') is evaluated first. Any non-empty string in python has truthy value. So the first operand evaluates to True because it has 3 elements: t,x,t. And going back to the line where * if x is false, its value is returned; ..., yis evaluated. Soy``` is png which is a non-empty string.
This python will evaluate the las operand and return the resulting value, which here is True.
Of course p[-3:]!=True is True and True is returned.
In second part when you do ('txt' and 'jpg'), it evaluates to 'jpg'.
So effectively, you are trying to do is:
p[-3:] != 'jpg'
and since p[-3:] evaluates to 'txt'
therefore,
p[-3:] != ('txt' and 'jpg')
evaluates to True.
In the first part:
p='/content/Images_of_Waste/img/PET968.txt'
p[-3:]!='txt' and p[-3:]!='jpg'
p[-3:]!='txt' return True
p[-3:]!='jpg' return False
therefore,
True and False return False

"Nonetype" error while being assigned to variables

Just started my Programming 1 class, and we were assigned to create a quiz, and tally up the final score at the end. As a result I created this simple statement to play after every question.
if answer_1 == correct_1:
a1 = 1 and print("You are correct!")
else:
a1 = 0 and print("You are incorrect.")
However, at the end it is telling me I cannot add an integer and a NoneType. The wrong answers (zeroes) are being applied fine, it's when the answer is right that it gets stored as a NoneType (which I know means nothing). I'm aware I'm doing some syntax wrong, but do not quite have the know how to fix it.
You are stuck with couple of things here:
you got precedence wrong since here and will be evaluated first, then =
print returns None, and 1 and None = None, while 0 and None = 0.
Here is a solution:
if answer_1 == correct_1:
a1 = 1
print("You are correct!")
else:
a1 = 0
print("You are incorrect.")
Edit:
Just wanted to point out why it stands that 1 and None = None and 0 and None = 0.
It is because Python evaluates boolean conditions lazily.
Here is what docs say about it:
The expression x and y first evaluates x; if x is false, its value is
returned; otherwise, y is evaluated and the resulting value is
returned.
The expression x or y first evaluates x; if x is true, its value is
returned; otherwise, y is evaluated and the resulting value is
returned.
Just for science
Having lazy evaluation of boolean conditions and = precedence you can mimic conditional (ternary) operator, construct you might find in other languages.
Definition of ternary operator: condition ? expr1 : expr2.
Explanation: If condition is true, the operator returns the value of
expr1; otherwise, it returns the value of expr2.
In Python, you can mimic this with: condition and expr1 or expr2.
Same applies as with definition of ternary operator. If contition evaluates to True, expr1 is returned. Otherwise, expr2 is returned.
Why I said just for science? Because although this looks great, it's not used often and may affect readability of your code.
Python’s and is a logical operator. It takes two values (either side) and returns True or False.
Since it's homework, I'll give you a strong hint. and doesn't work the way you're thinking here. You can have more than one line within an if statement.

Python - logical evaluation order in "if" statement

In Python we can do this:
if True or blah:
print("it's ok") # will be executed
if blah or True: # will raise a NameError
print("it's not ok")
class Blah:
pass
blah = Blah()
if blah or blah.notexist:
print("it's ok") # also will be executed
Can somebody point me to documentation on this feature?
Is it an implementation detail or feature of the language?
Is it good coding style to exploit this feature?
The or and and short circuit, see the Boolean operations documentation:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Note how, for and, y is only evaluated if x evaluates to a True value. Inversely, for or, y is only evaluated if x evaluated to a False value.
For the first expression True or blah, this means that blah is never evaluated, since the first part is already True.
Furthermore, your custom Blah class is considered True:
In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets). All other values are interpreted as true. (See the __nonzero__() special method for a way to change this.)
Since your class does not implement a __nonzero__() method (nor a __len__ method), it is considered True as far as boolean expressions are concerned.
In the expression blah or blah.notexist, blah is thus true, and blah.notexist is never evaluated.
This feature is used quite regularly and effectively by experienced developers, most often to specify defaults:
some_setting = user_supplied_value or 'default literal'
object_test = is_it_defined and is_it_defined.some_attribute
Do be wary of chaining these and use a conditional expression instead where applicable.
This is called short-circuiting and is a feature of the language:
http://docs.python.org/2/tutorial/datastructures.html#more-on-conditions
The Boolean operators and and or are so-called short-circuit operators: their arguments are evaluated from left to right, and evaluation stops as soon as the outcome is determined. For example, if A and C are true but B is false, A and B and C does not evaluate the expression C. When used as a general value and not as a Boolean, the return value of a short-circuit operator is the last evaluated argument.
It's the way the operators logical operators, specifically or in python work: short circuit evaluation.
To better explain it, consider the following:
if True or False:
print('True') # never reaches the evaluation of False, because it sees True first.
if False or True:
print('True') # print's True, but it reaches the evaluation of True after False has been evaluated.
For more information see the following:
The official python documentation on boolean operations
A stack overflow question regarding short circuitry in python
With the or operator, values are evaluated from left to right. After one value evaluates to True, the entire statement evaluates to True (so no more values are evaluated).
Official documentation
It's a feature of the language
There is nothing wrong with using its functionality

Logical OR operation with -1

Why is the output different for the following logical operations that I tried in python?
-1 or 1
1 or -1
First returns -1 and second returns 1
and and or are both lazy; they evaluate operands until they can decide the result (and stops at the first False operand; or stops at the first True operand). They return the last operand evaluated, as noted in the documentation:
Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value.
Read the documentation:
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
Both first parts -1 and 1 are evaluated True and therefore returned. The second part is ignored.
The or operator short-circuits. It returns the first value that is True in a boolean context, or the last evaluated expression otherwise. -1 and 1 are both True in a boolean context, so you get the first number.
0, None and all empty containers evaluate to False.
For example:
>>> 0 or 5
5
>>> '' or []
[]
In or condition if first condition is true, second is not evaluated,
I think the OP expects the return value of 'or' to be either True or False (as would be the case for boolean operators in some other languages.)
Python, like Perl, simply returns the first "true" value (where "true" means nonzero for numbers, non-empty for strings, not None, etc.)
Similarly, 'and' returns the last value if and only if both are "true".
He would probably be even more surprised by the result of something like
{'x':1} or [1,2,3]
Perl programmers often use this construct idiomatically (as in open(FILE, "foo.txt") || die; I don't know if that's as common in Python.
(see man)

Categories