0

I am trying to understand the __and__ method of the abstract base int Class. Here I have called the method two different ways. In nearly all cases, the two ways each behave as I expect, they output the second value, because both values are "truthy". But in the special case that the sum of the two numbers = -1, then the first way prints 0. Can anyone say why?

value = -4
print(value.__and__(3)) # prints 0
print(value and 3)         # prints 3

2 Answers2

2

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).

cglacet
  • 8,873
  • 4
  • 45
  • 60
0

A classmate pointed out that the and() method uses "bitwise and". Not the normal AND. Also, I was using signed integers in my calculations instead of two's complement.