Question: I am confused as to when I should use Boolean vs bitwise operators

* `and` vs `&`
* `or` vs `|`

Could someone enlighten me as to when do i use each and when will using one over the other affect my results?

Answer: 
Here are a couple of guidelines:

* Boolean operators are usually used on *boolean* values but bitwise operators are usually used on *integer* values.
* Boolean operators are *short-circuiting* but bitwise operators are *not* short-circuiting.

The short-circuiting behaviour is useful in expressions like this:

```
if x is not None and x.foo == 42:
    # ...

```

This would not work correctly with the bitwise `&` operator because both sides would always be evaluated, giving `AttributeError: 'NoneType' object has no attribute 'foo'`. When you use the boolean `and`operator the second expression is not evaluated when the first is False. Similarly `or` does not evaluate the second argument if the first is True.
The general rule is to use the appropriate operator for the existing operands. Use ***boolean*** (logical) operators with ***boolean*** operands, and ***bitwise*** operators with (wider) ***integral*** operands (note: *False* is equivalent to ***0***, and *True* to ***1***). The only "tricky" scenario is applying boolean operators to non boolean operands.   
Let's take a simple example, as described in [[SO]: Python - Differences between 'and' and '&'](https://stackoverflow.com/questions/50446174/python-differences-between-and-and):   
`5 & 7` *vs.* `5 and 7`.

For the *bitwise **and*** (**&**), things are pretty straightforward:

> 
> 
> ```py
> 5     = 0b101
> 7     = 0b111
> -----------------
> 5 & 7 = 0b101 = 5
> 
> ```
> 
> 

For the *logical **and***, here's what [[Python.Docs]: Boolean operations](https://docs.python.org/3/reference/expressions.html#boolean-operations) states (**emphasis** is mine):

> 
> (Note that neither [and](https://docs.python.org/3/reference/expressions.html#and) nor [or](https://docs.python.org/3/reference/expressions.html#or) restrict the value and type they return to *False* and *True*, but rather **return the last evaluated argument**.
> 
> 
> 

**Example**:

> 
> 
> ```py
> >>> 5 and 7
> 7
> >>> 7 and 5
> 5
> 
> ```
> 
> 

Of course, the same applies for ***|*** *vs.* *or*.