Expressions in programming, like in Mathematics, are used to compute results of combining some values. In programming, the expressions are more advanced and can evaluate to a wide variety of values belonging to different types.

Expressions are one of the building blocks of statements, and while an expression can stand by itself to form a complete statement, in most cases, they are combined with other entities, including loops, branches, functions, etc., to form statements

Operators, on the other hand, are used to join the values which forms an expression. These values can be simple such as integers and others can be more complex such as another expression or even the return value of a function.

We will look on how Expressions are used in Python, from simple one value expressions, to how we can form more complex ones using the operators available.

## Operators and operands

Operators together with operands are the building blocks of Python expressions. Operators by themselves do not hold any value and using them without necessary operands will raise a SyntaxError.

An Operand is an entity in a Python expression whose value is well defined for example an integer, a string, a list e.t.c. Operators are used with one or more operands in a systematic way, to get a fresh value from the operand(s).

It is worth noting that Python allows operator overloading in objects, meaning that a user can define the work of an operator in the context of a user defined object. Operator overloading is beyond the scope of this article and we will only focus on the standard use of the operators as specified by Python.

Operators in Python can be grouped into four categories according to the type of operation they are used in, that is:

**arithmetic operators****relational operators****logical operators****bit-wise operators**

Another grouping mechanism which can be used on operators is by the number of operands that an operator specifies. Grouping them this way we get:

**unary operators****binary operators**

The word **uni **as you might already know means one and the word **bi **means two. The unary operators as you might have deduced from the previous statement , specifies only one operand while the binary operators specifies two operands. We write unary operators in **prefix **form, meaning that the operator appears before the single operand and in binary operators, the operator is placed in-between the two operands , this is referred to as the **infix **form.

## Arithmetic Operators

Most arithmetic operators are familiar from Mathematics, some of them are used just the way they are used in math while others may differ or have polymorphic usage when used in programming. In this context, they are used with numeric types: **int, float** and **complex. **The following table shows the 7 arithmetic operators available in Python.

Operator | Operation |
---|---|

`+` |
Addition |

`-` |
Subtraction |

`*` |
Multiplication |

`/` |
Division |

`//` |
Floor Division |

`%` |
Modulo |

`**` |
Power |

**Addition**

The plus sign ( **+ **) is used as the addition operator, it is one of the operators in Python that can be used in the binary form as well as the unary form. Used in binary form ( with two operands ), the operator is used to get the standard arithmetic sum of its operands. In the unary form( one operand ) , it is used as an identity operator and it returns the same value as the operand. The examples below demonstrates some of the operator's usage:

Prototype | Example |
---|---|

(int + int) -> int | 7 + 5 -> 12 |

(float + float ) -> float | 3.0 + 6.0 -> 9.0 |

(complex + complex) -> complex | 3j + 5j - > 8j |

(float + int) -> float | 5.0 + 10 -> 15.0 |

+ (int) -> int | +(-9) -> -9 |

+ (float) -> float | +(5.0) -> 5.0 |

+ (complex) -> complex | +3j -> 3j |

**Subtraction**

The hyphen ( **- **) is used as the subtraction operator , it can be used in both binary and unary form. The binary form is used for subtraction and returns the standard difference of it's operands while the unary form is used to negate the value of the operand. Examples:

Prototype | Example |
---|---|

(int - int) -> int | 7 - 5 -> 2 |

(float - float ) -> float | 9.0 - 6.0 -> 3.0 |

(complex - complex) -> complex | 9j - 5j - > 4j |

(float - int) -> float | 5.0 - 10 -> -5.0 |

- (int) -> int | -(-9) -> 9 |

- (float) -> float | -(5.0) -> -5.0 |

- (complex) -> complex | -3j -> -3j |

**Multiplication**

The asterisk ( *** **) is used to evaluate the standard arithmetic product of the operands, it only takes the binary form. Some use cases are:

Prototype | Example |
---|---|

(int * int) -> int | 7 * 5 -> 35 |

(float * float ) -> float | 9.0 * 7.0 -> 63.0 |

(complex * complex) -> complex | 3j * 5j -> -12 + 0j |

(float * int ) -> float | 6 * 8.0 -> 48.0 |

**Division**

The forward slash( **/** ) is used for evaluating the arithmetic quotient of the operands, it only takes the binary form. Some use cases are:

You should always keep in mind that using these operator even with all operands being integers always return a **float **result.

Prototype | Example |
---|---|

(int / int) -> float | 12 / 3 -> 4.0 |

(float / float ) -> float | 30.0 / 5.0 -> 6.0 |

(complex / complex) -> complex | 3j / 5j -> .06 + 0j |

**Floor Division**

The floor of a given value is the closest integral value lower than it for example the floor value of 2.9 is 2 , while the ceil value is the closest integral value upper of the number for example the ceil value of 2.9 will be 3 .The floor value for a number has a lot of use cases in real life and Python provides an operator for evaluating it.

Double forward slashes( **//** ) are used to denote floor division operation. While the normal division in python i.e using a single slash, always returns a floating result, floor division returns an integer value if both operands are integers and a floating value if any of the operand is a float. This operation only works with **int** and **float ** types and can only be used in the binary form. the following table shows some use cases:

Prototype | Example |
---|---|

(int // int) -> int | 12 // 3 -> 4 |

(float // float ) -> int | 3.0 // 5.0 -> 0.0 |

(float // int ) -> int | 9.0 // 3 -> 3.0 |

**Modulo Operation**

The percentage sign (** % **) is used to perform modulo operation. The operator can only be used in the binary form and it is used to get the remainder value after dividing the left operand with the right operand. The return value i.e the remainder , always inherits the sign of the divisor( right operand ), so if the divisor is negative, the modulo results will be negative and if the divisor have a positive value, the results will be positive. The following table shows some use cases.

Prototype | Example |
---|---|

(int % int) -> int | 12 % 3 -> 0 |

(float % float ) -> float |
3.0 % 5.0 -> 3.0 |

(float % int ) -> float | 9.0 % -3 -> -0.0 |

**Power**

Double asterisks ( **** **) are used to perform power operation. It can only be used in the binary form , following table summarizes some use cases:

Prototype | Example |
---|---|

(int ** int) -> int | 2 ** 3 -> 8 |

(float ** float ) -> float | 3.0 ** 5.0 -> 243.0 |

(complex ** complex ) -> complex | 2j ** 3j -> (-0.00437 + 0.00784j) |

As you might have observed, the arithmetic operations usually returns results that matches their operand types and if the operands used are of different types the result is normally of the type with higher precedence than the other, for example using most operators with an int and a float operand will return a floating value.

##### Type conversion

The arithmetic operators have uses beyond what we discussed above, in the various examples, you have seen how we can use an operator with operands of differing types for example adding an integer to a floating value. Operations of that type requires implicit type conversions which we will discuss here.

The operator signs in Python converts operands given into necessary types before they are evaluated, they achieve this by using a well established hierarchy with `complex`

type on top and the `bool`

type ot the bottom of the hierarchy as follows:

`bool -> int -> float -> complex`

Whenever operands of differing types are encountered, the one at a lower level is promoted to the type of the other operand . This is the most logical approach since for example, there is no integer equivalent to 5.5 but there is a float for any given integer for example for 5 it is 5.0 .

##### Arithmetic on boolean Values

To perform arithmetic operations on boolean values, the values are first promoted to integer type, the results are therefore of type `int`

too. The boolean **False **is promoted to its integer value which is 0 and **True **to it's integer value which is 1.

```
False + False
//0
True + True
//2
False + True
//1
True + False
//1
```

##### Arithmetic operators on strings

Two arithmetic operators **+ **and *** **are overloaded to support operations on strings. The **+ **operator is used for **concatenating **two strings while the *** **operator is used for **replicating **a string number of times specified, the operator takes an integer and a string as it's operands.

`print("Hello, " + "World!")`

Hello, World!

`print("Hello" * 3)`

HelloHelloHello

## Relational Operators

These operators always returns a boolean value i.e **True **or **False , **and are used to test whether a certain relation holds in it's operands.All of these operands operates in binary form meaning that each requires two operands. The following table summarizes te 9 relational operators available in Python and the operations they are used to perform.

Operator | Name | Semantics |
---|---|---|

`==` |
equals | True when the operands have equal values |

`!=` |
not equals | True when the operands have unequal values |

`<` |
less than | True when the left operand is less than the right operand |

`>` |
greater than | True when the left operand is greater than the right operand |

`<=` |
less than or equals | True when the left operand is less than or equal to the right operand |

`>=` |
greater than or equals | True when the left operand is greater than or equal to the right operand |

`is ` |
object identity | True when the left operand refers to the same object as the right operand. |

`in` |
inclusion | True when the left operand appears in the right operand(which is an iterable) |

`not in` |
negate inclusion | True when the left operand does not appear in the right operand(which is an iterable) |

We can group the relational operators according to the type of operations they perform:

- Equality and identity (
**==, !=, is**) - Ordered Comparison (
**<, >, <=, >=**) - inclusion (
**in, not in**)

```
5 > 10
//False
5 < 10
//True
5 == (2 + 3)
//True
10 != (5 * 2)
//False
12 >= (3 * 4)
//True
12 <= (4*5)
//False
2 in [5, 3, 4, 7, 9]
//False
"W" in "Hello, World!"
//True
"r" not in "Hello, World!"
//False
```

## Logical Operators

These operators are used to perform boolean logic ,they are mostly used with boolean operands. If the operand(s) are not of the

type i.e **bool***True *or *False, *their boolean values are evaluated in advance. These operators are summarized in the following table:

Operator | Name | Semantics |
---|---|---|

`and` |
Conjunction | True if both operands have a boolean value of True |

`or` |
Disjunction | True if either or both operands have a boolean value of True |

`not` |
Negation | True if none of the operands have a boolean value of True |

`!=` |
exclusive or | True if either of the operand is True (returns False if both are True) |

To perform complex operations with the logical operators, the programmers needs to understand the expected results of using these operators with varying operands. The following truth table summarizes the results of applying the operators on two values *a *and *b *each holding a given boolean value.

a |
b |
a and b |
a or b |
not b |
a != b |
---|---|---|---|---|---|

`False` |
`False` |
`False` |
`False` |
`True` |
`False` |

`False` |
`True` |
`False` |
`True` |
`False` |
`True` |

`True` |
`False` |
`False` |
`True` |
`*` |
`True` |

`True` |
`True` |
`True` |
`True` |
`*` |
`False` |

The `not `

operator is a unary operator and it simply checks whether an object has a boolean value of `False`

, that is why it's column in the table above looks a little bit different

## Bit-wise Operators

These operators operates on it's operands which are normally integers at bit level. There are six bit-wise operators, their usage are shown on the table below.

Bit-wise | Operator | Examples |
---|---|---|

and | `&` |
0011 & 0101 -> 0001 |

inclusive or | `|` |
0011 | 0101 -> 0111 |

not | `~` |
~01 -> 10 |

exclusive or | `^` |
0011 ^ 0101 -> 0110 |

shift left | `<<` |
101 << 2 -> 10100 |

shift right | `>>` |
101 >> 2 -> 1 |