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.
Related
Are the following two pieces of code equivalent?
if x is not None:
print("hello")
and:
if x is (not None):
print("hello")
No, there are not equivalent. is not is an operator, the only operator that I know of with whitespace, according to Python's documentation:
The operators is and is not test for an object’s identity: x is y is true if and only if x and y are the same object. An Object’s identity is determined using the id() function. x is not y yields the inverse truth value.
In other words, these two expressions are equivalent and always equal to each other:
(x is not None) == (not (x is None)) # always returns True
In your second example, you are not using the is not operator, but the is operator and the not operator separately. not None evaluates to True. So we can conclude that the following two expressions are equivalent and are always equal to each other:
(x is (not None)) == (x is True) # always returns True
Kindly help me understand why this works. The code below lists duplicates in an iterable. However, the use of the or operator behaves like the else in an if..else statement..
j = set()
my_list = [1, 2, 3 ,3 , 3 ,4, 4]
j_add = j.add
twice = set(x for x in my_list if x in j or j_add(x))
print list(twice)
Would expect the line to be:
twice = set(x for x in my_list if x in j else j_add(x))
Thought or returns a boolean not a value
The or operator returns the last evaluated argument, which may or may not be a Boolean.
This behavior is explained 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.
Of course, it helps to remember what is interpreted as false and what is interpreted as true:
[T]he 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.
So in the expression:
A = B or C
As #MartijnPieters points out in a comment, an or expression short-circuits. If the first argument (B in this case) is interpreted as true, the entire expression must be true so the second argument (C) is never evaluated. Therefore the first argument (B) is "the last evaluated argument" and is what is returned. However, if the first argument (B) is interpreted as false, the second argument (C) must still be evaluated to determined the truthiness of the expression (no short-circuit takes place). In that case, "the last evaluated argument" is the second argument (C), which is returned regardless of whether the expression evaluates true or false.
It effectively accomplishes the same as the Conditional Expression:
A = B if B else C
However, Conditional Expressions were only added to Python in version 2.5, while the Boolean Operator behavior has existed from the beginning (or at least for a very long time). Most seasoned Python programmers will easily recognize and are in the habit of using A = B or C. Conditional Expressions are commonly reserved for more complex conditions that won't work with a simple or (for example in A = B if X else C the condition is not based on the truthiness of B but X, which could be anything from a simple value to a complex expression).
However, you need to be careful because, as JaredGoguen points out in his answer, changing the or to an else in the OP's sample actually changes the behavior of the code. That code was written to depend on this specific behavior of the or operator. You can't just replace any use of or for assignment with a Conditional Expression. Additional refactoring may be needed as well.
I might make a value judgment here and say that this is not good code because it is using the short-circuiting behavior of or to produce a side-effect.
Consider the given conditional: if x in j or j_add(x).
When x in j, the or short-circuits, skips the j_add(x) part of the conditional, and evaluates as True.
When x not in j, the statement j_add(x) is checked for its truthiness. This method returns None, which is falsy, and so or evaluate as False.
So, the entire conditional will evaluate the same as x in j. However j_add(x) has the side-effect of adding x to j! This side-effect is being exploited in order to record the unique members my_list in a quick-and-dirty comprehension.
Changing the or to an else would still construct j as desired, but it would inappropriately add None, the return value of j_add(x), to twice.
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.
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).
I notice there is a comparison operator is not. Should I literally translate it into
!=
instead of
== not
?
To expand on what Ignacio said:
a == b and a != b test whether two objects have the same value. You can override an object's __eq__ and __ne__ methods to determine what that means.
a is b and a is not b test whether two objects are the same thing. It's like doing id(a) == id(b).
It's not a relational comparison; it's identity. And it translates to not (A is B).
Python 2.7.3 documentation, 5.9. Comparisons:
The operators <, >, ==, >=, <=, and != compare the values of two objects.
and about operator is in the same chapter:
The operators is and is not test for object identity: x is y is true if and only if x and y are the same object. x is not y yields the inverse truth value.
A != B
means that "A is not equal to B", not "A is equal to not B".