Python’s ** bitwise AND** operator

`x & y`

performs *logical AND*on each bit position on the binary representations of integers

`x`

and `y`

. Thus, each output bit is 1 if both input bits at the same position are 1, otherwise, it’s 0. For example, the integer expression 4 & 3 is translated to binaries 0100 & 0011 which results in 0000 because all four input bit positions are different.In this example, you apply the ** bitwise AND **operator to two integers 32 and 16:

>>> 32 & 16 0

The expression `32 & 16`

operates on the bit representations `"010000"`

(decimal 32) and `"001000"`

(decimal 16) and performs ** bitwise AND**. As all i-th bit positions are different, the result is 0:

First Operand `x` | 1 | 0 | 0 | 0 | 0 | 0 |

Second Operand `y` | 0 | 1 | 0 | 0 | 0 | 0 |

`x & y` | 0 | 0 | 0 | 0 | 0 | 0 |

Similarly, let’s have a look at a slightly modified example to showcase the ** bitwise AND **operator:

>>> 31 & 15 15

You can see this in the following visualization:

First Operand `x` | 1 | 1 | 1 | 1 | 1 |

Second Operand `y` | 0 | 1 | 1 | 1 | 1 |

`x & y` | 0 | 1 | 1 | 1 | 1 |

The decimal representation of the bit sequence `"01111"`

is 15.

## Python Bitwise & Operator Example

Here’s the result of the ** bitwise AND **operator

`x & y`

when applied to a couple of example integer operands `x`

and `y`

:x (int) | y (int) | x (binary) | y (binary) | x & y (binary) | x & y (int) |
---|---|---|---|---|---|

0 | 1 | 0 | 1 | 0 | 0 |

0 | 3 | 00 | 11 | 00 | 0 |

3 | 5 | 0011 | 0101 | 0001 | 1 |

33 | 129 | 000100001 | 010000001 | 000000001 | 1 |

15 | 7 | 01111 | 00111 | 00111 | 7 |

14 | 7 | 01110 | 00111 | 00110 | 6 |

You can see those examples in the following Python script:

>>> 0 & 1 0 >>> 0 & 3 0 >>> 3 & 5 1 >>> 33 & 129 1 >>> 15 & 7 7 >>> 14 & 7 6

Next, you’ll learn how to use the operator on negative integers. But first, you need to understand how negative integers are represented in the first place. This will boost your computer science skills, so keep reading! ?β?

## Representing Negative Integers in Binaries

Python uses so-called ** complementary binaries** to represent negative integers. The first bit of a complementary binary is the sign (0: positive, 1: negative). All remaining bits encode the number. You write a negative number -x as the bit pattern for (x-1) and flip all bits from 1 to 0 and from 0 to 1 (complement).

Here are two simple examples:

- To represent
`x = -1`

using 8 bits you first calculate`(1-1) = 0`

and then flip all bits to calculate`"11111111"`

. - To represent
`x = -10`

using 8 bits you first calculate`(10-1) = 9`

which is`"00001001"`

in binary format. Then, you complement all bits to determine the negative (complementary) binary`"11110110"`

.

Let’s use this knowledge in a couple of examples to showcase the working of the *bitwise AND operator* on negative integers:

## Python Bitwise AND & – Examples on Negative Integers

Here’s the result of the bitwise and operator `x & y`

when applied to a couple of negative integer operands `x`

and `y`

:

x (int) | y (int) | x (binary) | y (binary) | x & y (binary) | x & y (int) |
---|---|---|---|---|---|

0 | -1 | 00000000 | 11111111 | 00000000 | 0 |

0 | -3 | 00000000 | 11111101 | 00000000 | 0 |

-3 | -5 | 11111101 | 11111011 | 11111001 | -7 |

You can see those examples in the following script:

>>> 0 & -1 0 >>> 0 & -3 0 >>> -3 & -5 -7

## Python Bitwise versus Logical AND: “and” vs “&”

Python’s “`and`

” operator performs a logical AND operation that returns `True`

if both operands are `True`

. Python’s “`&`

” symbol is a bitwise operator that works on the bit representations of the operands and performs a bit by bit operation. So, “`and`

” tests whether both operands are logically `True`

whereas “`&`

” performs bitwise AND operation on the operands.

When considering only a single bit, semantically, such as when comparing Booleans, the operators are the same:

>>> True and True True >>> True & True True

However, the difference becomes apparent if you use integer operands:

>>> 32 and 16 16 >>> 32 & 16 0

The first expression `32 and 16`

determines that the integer value 32 results in a Boolean `True`

, so it returns the second operand 16 as it performs the short-circuiting optimization.

The second expression 32 & 16 operates on the bit representations 10000 (decimal 32) and 01000 (decimal 16) and performs bit-wise AND. As all i-th bit positions are different, the result is 0:

First Operand x | 1 | 0 | 0 | 0 | 0 | 0 |

Second Operand y | 0 | 1 | 0 | 0 | 0 | 0 |

x & y | 0 | 0 | 0 | 0 | 0 | 0 |

Similarly, let’s have a look at another example to showcase the bitwise and operator:

>>> 31 & 15 15

You can see this in the following visualization:

First Operand x | 1 | 1 | 1 | 1 | 1 |

Second Operand y | 0 | 1 | 1 | 1 | 1 |

x & y | 0 | 1 | 1 | 1 | 1 |

The decimal representation of the bit sequence 01111 is 15.

## Python Bitwise AND Operator Overloading

To enable the bitwise AND operator on your custom object, use Python’s ** operator overloading** functionality. Overloading works through what is called

*magic methods*or

*dunder methods*(for “

**d**ouble-

**under**score methods”)

*.*For the bitwise AND operator, the magic method is the

`__and__(self, other)`

method. It should return a new custom object that is the result of the bitwise operation.Here’s a short overview of the Bitwise operators’ magic methods:

Bitwise Operator | Magic “Dunder” Method |
---|---|

`&` | `__and__(self, other)` |

`|` | `__or__(self, other)` |

`^` | `__xor__(self, other)` |

`~` | `__invert__(self)` |

`<<` | `__lshift__(self, other)` |

`>>` | `__rshift__(self, other)` |

Here’s an example of how to accomplish these bitwise operators on a custom class `Data`

. We marked this respective operator in the code:

class Data: def __init__(self, data): self.data = data def __and__(self, other): return Data(self.data & other.data) def __or__(self, other): return Data(self.data | other.data) def __xor__(self, other): return Data(self.data ^ other.data) def __invert__(self): return Data(~self.data) def __lshift__(self, other): return Data(self.data << other.data) def __rshift__(self, other): return Data(self.data >> other.data) x = 2 y = 3 print('Operands: \n', 'x =', x, '\n', 'y =', y) print() print('Bitwise AND: ', x & y) print('Bitwise OR: ', x | y) print('Bitwise XOR: ', x ^ y) print('Bitwise NOT: ', ~x) print('Bitwise LEFT-SHIFT: ', x << y) print('Bitwise RIGHT-SHIFT: ', x >> y)

The output is:

Operands: x = 2 y = 3 Bitwise AND: 2 Bitwise OR: 3 Bitwise XOR: 1 Bitwise NOT: -3 Bitwise LEFT-SHIFT: 16 Bitwise RIGHT-SHIFT: 0

## Bitwise Operators

Bitwise operators perform operations on the binary (bit) representation of integers. The following table gives a short overview of all existing bitwise operators. Note that we also provide the binary representation `100`

for the decimal integer `4`

, and `101`

for the decimal integer `5`

as a comment in the right column.

Operator | Name | Description | Example |
---|---|---|---|

`x = 4, y = 5` | |||

& | Bitwise AND | Performs logical AND on a bit-by-bit basis | `x & y` |

| | Bitwise OR | Performs logical OR operation on a bit-by-bit basis | `x | y` |

~ | Bitwise NOT | Performs logical NOT on a bit-by-bit basis, inverting each bit so that 0 becomes 1 and 1 becomes 0. Same as `-x-1` . | `~x` |

^ | Bitwise XOR | Performs logical “exclusive or” operation on a bit-by-bit basis | `x ^ y` |

>> | Bitwise right shift | Shifts binary of left operand to the right by the number of positions specified in right operand | `x >> 2` |

<< | Bitwise left shift | Shifts binary of left operand to the left by the number of positions specified in right operand | `x << 2` |