Our adventures in Python begin with a program to count the bits set to 1 in a positive integer, using shifting and masking.

```
def count_bits(x):
num_bits = 0
while x:
num_bits += x & 1
x >>= 1
return num_bits
```

The bitwise operators and what they are doing may not be immediately obvious to those coming from a world of arithmetic operators. `x & 1`

performs a 'bitwise and': that is to say, outputs a new value based on the corresponding bits of the two incoming values, each of whose bits is set to 1 if and only if that bit is 1 in both incoming values. Given that the second value we are passing in is 1, that means we effectively care only about the rightmost bit of `x`

here, as every other bit will be `& 0`

and therefore 0 by definition.

If the rightmost bit of `x`

is 1, we'll get a result of 1 and add this to `num_bits`

, otherwise `num_bits`

gets incremented (or not) by 0. (In binary, all odd numbers have a rightmost digit/bit of 1 and all even numbers have 0 there.)

But we don't want to count only the rightmost bit. Here's where the `>>`

or rightward shift operator comes in. It shifts each bit in the binary value n places, in this case 1 place, to the right.

```
>>> 1 >> 1
0
>>> 2 >> 1
1
>>> 3 >> 1
1
>>> 4 >> 1
2
>>> 8 >> 1
4
```

As we can see, if a single bit is shifted right we are simply left with no bits, i.e. 0. If either 2 (0b10) or 3 (0b11) shifts right we lose the least significant digit and are left with 0b1. 4 (0b100) becomes 2 (0b10) and 8 (0b1000) becomes 4. It is clear that `x >>= 1`

is equivalent to `x //= 2`

.

Our `count_bits`

function therefore keeps shifting bits rightward, checking each time for a 1, until the integer has been reduced to 0 and `while x`

therefore ceases to be truthy. O(1) computation per bit equals O(n) time complexity, where n is the number of bits in the integer. No doubt we can do better from here!