How does python evaluate this? - python

Can someone explain how these results are possible (python 2.6):
>>> 1<3>2
True
>>> (1<3)>2
False
>>> 1<(3>2)
False
I would think that one of the last two would match the first one, but apparently the operators in the first statement is somehow linked?!

Your first example shows comparison chaining. 1<3>2 means 1<3 and 3>2 (except each expression is evaluated only once). This applies to all comparison operators in Python.
Your second two examples force one comparison to be evaluated first, resulting in a boolean value which is then compared with the remaining integer.

In your first case 1<3>2 1 is actually lesser than 3 and 3 is greater than 2, so True.
In your second case (1<3)>2 (1<3) evaluates as True that represented as 1, so 1 is not greater than 2.
In your third case 1<(3>2), 1 is not lesser than True that represented as 1.

The last two statements compare booleans against an integer:
>>> True > 2
False
>>> 1 < True
False
The first statement is comparison chaining, which works for all boolean comparisons in Python. Note from the documentation:
Comparisons yield boolean values: True or False.
By placing parts of your expression in brackets, those parts get evaluated first and you end up with comparing integers and booleans.

As per docs,
Unlike C, all comparison operations in Python have the same priority, which is lower than that of any arithmetic, shifting or bitwise operation. Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics:
comparison ::= or_expr ( comp_operator or_expr )*
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
| "is" ["not"] | ["not"] "in"
Comparisons yield boolean values: True or False.
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

Related

Unexpected result with `in` operator chaining

As far as I know, the in operator in Python can't be chained or at least I couldn't find any info on it, here is my problem
Here is the code
arr = [1, True, 'a', 2]
print('a' in arr in arr) # prints False
print(('a' in arr) in arr) # prints True
What I don't understand is the first print, I know in the second the first in returns True and then it check if True is in arr, but what about the first one? Does it check if 'a' is in arr and then if arr is in arr?
The premise is false; the in operator can be chained. See Comparisons in the docs:
comp_operator ::= "<" | ">" | "==" | ">=" | "<=" | "!="
| "is" ["not"] | ["not"] "in"
So, just as with any other chained comparison, a in b in c is equivalent to (a in b) and (b in c) (except that b is only evaluated once.
The reason 'a' in arr in arr is false is that arr in arr is false. The only time x in x is true is if x is type that does substring comparisons for __contains__ (like str or bytes), or if it's a container that actually contains itself (like lst = []; lst.append(lst)).

The differences' between the operator "==" and "="

The differences' between the operator "==" and "=". When would each be used? Why would each be used?
In python and other languages like C,
"=" is a assignment operator and is used to assign a value to a variable.
Example: a=2 # the value of a is 2
whereas "==" is Comparison operator and is used to check whether 2 expressions give the same value .Equality check returns true if it succeeds and else return false.
Example: a=2 b=3 c=2
a==b (#false because 2 is not equal to 3)
a==c (#true because 2 is equal to 2)
= is used for assignment: e.g.: apple = 'apple'.
It states what is what.
== compares one value to another. Is 5 equal to 5 should be written like this: 5 == 5
An == expression evaluates to true, is an equality operator.
== has the value of two operands are equal make the condition or statement true.
= is an expression of assignment operator to the symbol of variables, arrays, objects.
Both operators are very important, and they work in different ways in every equivalent object. Their behavior in their operation is based on the identity of objects. Are reflation of their variables.
When using == in compares the values of two objects example having two cars from the same company and have the same identity and features and same looks.
The rule implies that the statement and condition to be trues
To use = operator is when to evaluate variables in an expression if both sides of the operator mean same or the objects are same if not same its expression will be false and if true the expressions or objects are same.

Testing second condition when first false

I have a simple program
temp='abc12a'
ver = 1
print(temp[-1].isdigit())
if temp[-1].isdigit() & int(temp[-1])!=ver:
print(temp[:-1]+t)
which gives the output
False
Traceback (most recent call last):
File "python", line 3, in <module>
ValueError: invalid literal for int() with base 10: 'a'
Why does the second condition even get checked when the first is false? Is there a way to only do the second if the first is true that is cleaner than two ifs?
The & operator in Python checks as a bitwise and. It does not short circuit. The and operator properly short circuits, which is the behavior you are looking for.
The boolean connectives are and, or and not.
& is a bitwise and.
From 5.10. Boolean operations:
or_test ::= and_test | or_test "or" and_test
and_test ::= not_test | and_test "and" not_test
not_test ::= comparison | "not" not_test
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.)
The operator not yields True if its argument is false, False otherwise.
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 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. Because not has to invert a value anyway, it does not bother to return a value of the same type as its argument, so e.g., not 'foo' yields False, not ''.)

python augmented assignment for boolean operators

Does Python have augmented assignment statements corresponding to its boolean operators?
For example I can write this:
x = x + 1
or this:
x += 1
Is there something I can write in place of this:
x = x and y
To avoid writing "x" twice?
Note that I'm aware of statements using &= , but I was looking for a statement that would work when y is any type, not just when y is a boolean.
The equivalent expression is &= for and and |= for or.
>>> b = True
>>> b &= False
>>> b
False
Note bitwise AND and bitwise OR and will only work (as you expect) for bool types. bitwise AND is different than logical AND for other types, such as numeric
>>> bool(12) and bool(5) # logical AND
True
>>> 12 & 5 # bitwise AND
4
Please see this post for a more thorough discussion of bitwise vs logical operations in this context.
No, there is no augmented assignment operator for the boolean operators.
Augmented assignment exist to give mutable left-hand operands the chance to alter the object in-place, rather than create a new object. The boolean operators on the other hand cannot be translated to an in-place operation; for x = x and y you either rebind x to x, or you rebind it to y, but x itself would not change.
As such, x and= y would actually be quite confusing; either x would be unchanged, or replaced by y.
Unless you have actual boolean objects, do not use the &= and |= augmented assignments for the bitwise operators. Only for boolean objects (so True and False) are those operators overloaded to produce the same output as the and and or operators. For other types they'll either result in a TypeError, or an entirely different operation is applied. For integers, that's a bitwise operation, sets overload it to do intersections.

Python 3 order of testing undetermined

string='a'
p=0
while (p <len(string)) & (string[p]!='c') :
p +=1
print ('the end but the process already died ')
while (p <1) & (string[p]!='c') :
IndexError: string index out of range
I want to test a condition up to the end of a string (example string length=1)
why are both parts of the and executed is the condition is already false!
as long as p < len(string). the second part does not even need executing.
if it does a lot of performance can be lost
You're not using proper boolean and. Use it and you won't see this problem. What you're using (&) is a bitwise comparison, which evaluates both sides.
Bitwise AND, "a & b", should be thought of as
function _bitwise_and(A,B):
# A and B are Python expressions
# which result in lists of 1's and 0's
a = A.evaluate()
b = B.evaluate()
return [ 1 if abit==1 and bbit==1 else 0 for abit,bbit in zip(a,b)]
so, graphically,
a: ... 0 1 1 0
b: ... 1 0 1 0
--------
a&b ... 0 0 1 0 <- each bit is 1 if-and-only-if the
corresponding input bits are both 1
and the result is a list of bits, packed into an integer.
.
Logical AND, "a and b", should instead be thought of as
function _and(A,B):
# A and B are Python expressions which result in values having truthiness
a = A.evaluate()
if is_truthy(a):
b = B.evaluate()
return b
else:
return a
.
Notice: if the result of A is falsy, B never gets evaluated - so if expression B has an error when evaluated, bitwise AND will result in an error while logical AND will not.
This is the basis for the common Python idiom,
while (offset in data) and test(data[offset]):
do_something_to(data[offset])
next offset
... because data[offset] is only evaluated if offset is a useable (non-error-producing) value.
By using '&' instead of 'and', you guarantee an error by evaluating data[last_offset+1] at the end of your loop.
.
Of course, this could have been avoided with another common idiom:
for ch in string if ch=='c':
do_something_to(ch)
which avoids IndexError problems altogether.
You need to use the boolean operators and and or rather than the bitwise operators & and |

Categories

Resources