The "problem" is not with the __and__
operator. The bitwise operator in python is not and
it's &
:
>>> (7).__and__(5) == (7 & 5)
True
As for how and
interacts with non boolean values, you can read this answer. For your particular case:
and
Returns the first Falsy value if there are any, else return the last value in the expression.
In your case, both -4
and 3
are non Falsy values, therefore the last value (3
) is returned. Considering what is considered Falsy we can also understand why -4 and 0 and 3 == 0
, ie., because 0
is Falsy.
Note that this behavior for the and
operator makes sense. It just extends the logic of the natural boolean and operator in the most natural way (or at least one of the most natural way). For example, True and False and False and x
, will return False
as soon as the first False
is encountered, while True and True and x
will simply return x
as all previous boolean values validate the global statement.
Finally, the apparently strange behavior of the bitwise operator when dealing with negative numbers comes from how negative numbers are encoded. Basically, to turn a positive number (eg, 4 = 000100) into a negative, you simply need to invert all it's bits (111011) then add 1 (111100 = -4). In the evaluating 3 & -4
is equivalent to solving the following:
000011
& 111100
--------
= 000000
For the same reason x & -4
will evaluate to 4
for any x
in 4, 5, 6, 7
(the two low digits are always canceled by the terminating zeros in the binary representation of -4 (111100).