# Operators

Course: [Python](https://www.devtutorials.ai/learn/python) · Section: Getting Started
Source: https://www.devtutorials.ai/learn/python/getting-started/operators

> The symbols that do the work in Python: arithmetic, comparison, assignment shortcuts, and, or, is, in, bitwise, the walrus operator, and precedence.

A calculator has buttons: plus, minus, times, divide.

You press a button, give it two numbers, and it gives you an answer.

Python works the same way, and the buttons are symbols you type.

```python runnable title="Four familiar buttons"
maths = 78
science = 85

print(maths + science)
print(maths - science)
print(maths * 2)
print(maths / 2)
```

Each symbol took two numbers and produced one answer. Those symbols are called **operators**.

Python has more of them than a calculator does. Some compare two values. Some ask yes-or-no questions. One checks whether something is inside a list. They all follow the same shape: give it values, get an answer back.

## What You Will Learn

In this lesson, you will learn:

- The seven arithmetic operators, including the two that surprise people
- How to compare two values and get `True` or `False`
- Shortcuts like `+=` that update a variable in place
- `and`, `or` and `not`, and why Python sometimes stops reading halfway
- A one-line way to choose between two values
- The difference between "the same value" and "the same object"
- How to check whether something is inside a list or a piece of text
- The operators that work on the bits inside a number
- The walrus operator `:=`, which stores a value and uses it at once
- The order Python applies all of these in, and how brackets take control

Do not worry about memorizing every operator right away. Focus on understanding what each group does and when to use it.

## Introduction to Operators

An operator is a symbol that takes values and produces a new value.

### What Are Operators?

An **operator** is a symbol that takes one or two values and produces a new value.

For example, `+` takes two numbers and produces their total. `>` takes two numbers and produces `True` or `False`.

### Why Operators Are Used

Without operators a program could only store values and print them back. Operators are what let it work something out.

```python runnable title="Working something out, not just storing it"
total_marks = 450
subjects = 6

average = total_marks / subjects

print("Average:", average)
print("Passed:", average >= 35)
```

Two operators did real work here. `/` found the average. `>=` turned that average into a yes-or-no answer.

### Operands and Expressions

The values an operator works on are called **operands**. The whole thing — operands and operator together — is an **expression**.

In `78 + 85`, the numbers 78 and 85 are the operands, `+` is the operator, and `78 + 85` is the expression.

Every expression produces a value, so an expression can be used inside a bigger expression.

```python runnable title="Small expressions inside a bigger one"
maths = 78
science = 85
english = 60

print((maths + science + english) / 3)
```

Python worked out the brackets first, got 223, then divided by 3.

### Types of Operators in Python

Python operators are grouped by what they do. Some perform calculations, some compare values, and some help make decisions. Here is the full list, and you will meet every group in this lesson.

<div className="tscroll">

| Group | Symbols | What they do |
|---|---|---|
| Arithmetic | `+` `-` `*` `/` `//` `%` `**` | do sums |
| Comparison | `==` `!=` `>` `<` `>=` `<=` | compare two values |
| Assignment | `=` `+=` `-=` `*=` `/=` `//=` `%=` `**=` | store and update |
| Logical | `and` `or` `not` | combine yes-or-no answers |
| Identity | `is` `is not` | ask whether two names hold the same object |
| Membership | `in` `not in` | ask whether a value is inside something |
| Bitwise | `&` `\|` `^` `~` | work on the bits inside a number |
| Walrus | `:=` | store a value and use it in the same line |

</div>

## Arithmetic Operators

Arithmetic operators do sums. They are the ones you already know from a calculator, plus a few Python extras.

### Addition (+)

`+` adds two numbers together, or joins two pieces of text.

```python runnable title="Adding"
maths = 78
science = 85

print(maths + science)
```

`+` also joins text, which you met in the last lesson. The type of the values decides which job it does.

### Subtraction (-)

`-` subtracts one number from another.

```python runnable title="Subtracting"
marks = 78

print(100 - marks)
```

### Multiplication (*)

`*` multiplies two numbers, or repeats text a number of times.

```python runnable title="Multiplying"
marks_per_test = 25
tests = 4

print(marks_per_test * tests)
```

`*` repeats text as well:

```python runnable title="Multiplying text"
print("-" * 20)
print("ab" * 3)
```

### Division (/)

`/` always gives a `float`, even when the numbers divide exactly.

```python runnable title="Division always gives a decimal"
print(450 / 6)
print(10 / 2)
print(type(10 / 2))
```

`10 / 2` is `5.0`, not `5`. This surprises many beginners, and it is on purpose: `/` gives the exact answer, including any fraction, and Python always shows that answer as a decimal.

Dividing by zero stops the program:

```python runnable expect-error title="Dividing by zero"
subjects = 0

print(450 / subjects)
```

There is no answer to dividing by zero, so Python stops the program with a `ZeroDivisionError`. Check for zero before you divide.

### Floor Division (//)

`//` divides and throws away the fraction, giving a whole number.

```python runnable title="Division without the fraction"
print(17 / 5)
print(17 // 5)
```

`17 / 5` is 3.4. `17 // 5` is 3.

Use `//` when a fraction makes no sense. You cannot have 3.4 full boxes.

```python runnable title="How many full rows of 5?"
students = 17
per_row = 5

print("Full rows:", students // per_row)
print("Left over:", students % per_row)
```

### Modulus (%)

`%` gives what is left over after a division. People usually read it aloud as "mod".

```python runnable title="What is left over"
print(17 % 5)
print(20 % 5)
```

17 divided by 5 is 3 with 2 left over, so `17 % 5` is 2. Nothing is left over from 20, so `20 % 5` is 0.

`% 2` is the usual way to ask whether a number is even:

```python runnable title="Even or odd"
for number in [10, 7, 4]:
    print(number, "even?", number % 2 == 0)
```

A leftover of 0 means the number divided exactly, so it is even.

### Exponentiation (**)

`**` raises a number to a power.

```python runnable title="Powers"
print(2 ** 3)
print(5 ** 2)
print(9 ** 0.5)
```

`2 ** 3` is 2 multiplied by itself 3 times, which is 8. A power of `0.5` is the square root, so `9 ** 0.5` is 3.0.

### Arithmetic Expressions

Put them together and you have a real calculation.

```python runnable title="A percentage, start to finish"
TOTAL_POSSIBLE = 600
scored = 489

percent = scored / TOTAL_POSSIBLE * 100

print("Percent:", round(percent, 1))
print("Whole part:", int(percent))
```

<div className="tscroll">

| Operator | Name | Example | Result |
|---|---|---|---|
| `+` | add | `78 + 85` | `163` |
| `-` | subtract | `100 - 78` | `22` |
| `*` | multiply | `25 * 4` | `100` |
| `/` | divide | `17 / 5` | `3.4` |
| `//` | floor divide | `17 // 5` | `3` |
| `%` | modulus | `17 % 5` | `2` |
| `**` | power | `2 ** 3` | `8` |

</div>

## Comparison Operators

Comparison operators ask questions about values. The answer is always either `True` or `False`.

### Equal To (`==`)

`==` asks whether two values are the same. Two equals signs, not one.

```python runnable title="Asking, not assigning"
marks = 78

print(marks == 78)
print(marks == 85)
```

One `=` stores a value. Two `==` ask a question. Mixing them up is the most common beginner mistake, in Python and in most other languages.

### Not Equal To (`!=`)

`!=` asks whether two values are different.

```python runnable title="Asking whether two values differ"
marks = 78

print(marks != 85)
print(marks != 78)
```

### Greater Than (`>`)

`>` checks whether the first value is larger than the second.

```python runnable title="Greater than"
print(78 > 35)
print(20 > 35)
```

### Less Than (`<`)

`<` checks whether the first value is smaller than the second.

```python runnable title="Less than"
print(20 < 35)
```

### Greater Than or Equal To (`>=`)

`>=` checks whether the first value is larger than or equal to the second.

```python runnable title="At least"
PASS_MARK = 35

print(35 >= PASS_MARK)
print(34 >= PASS_MARK)
```

A mark of exactly 35 passes, which is why `>=` is the right operator for a pass mark and `>` is not.

### Less Than or Equal To (`<=`)

`<=` checks whether the first value is smaller than or equal to the second.

```python runnable title="At most"
print(34 <= 35)
print(35 <= 35)
```

### Comparison Expressions

Comparisons are what decisions are made from.

```python runnable title="A comparison used as an answer"
PASS_MARK = 35
marks = 78

passed = marks >= PASS_MARK

print("Passed:", passed)
print(type(passed))
```

Python also lets you chain comparisons, which reads exactly like a mathematics line:

```python runnable title="Two comparisons in one"
marks = 78

print(35 <= marks <= 100)
```

`35 <= marks <= 100` asks whether the marks sit between 35 and 100. Most languages need two comparisons joined by an `and` to say this.

## Assignment Operators

Assignment operators store values and update variables. The basic `=` stores a value, and the combined operators like `+=` do an operation and store the result in one step.

### Assignment (=)

`=` puts the value on the right into the name on the left.

```python runnable title="Storing a value"
marks = 78

print(marks)
```

### Add and Assign (+=)

`marks += 5` means `marks = marks + 5`. It is shorter, and it says "update this" more clearly.

```python runnable title="Adding to what is already there"
score = 0

score += 10
score += 20

print(score)
```

### Subtract and Assign (-=)

```python runnable title="Taking some away"
lives = 3
lives -= 1

print(lives)
```

### Multiply and Assign (*=)

```python runnable title="Multiplying in place"
marks = 40
marks *= 2

print(marks)
```

### Divide and Assign (/=)

```python runnable title="Dividing in place"
total = 450
total /= 6

print(total)
```

The answer is `75.0`, a decimal, because `/` always gives a decimal.

### Floor Divide and Assign (//=)

```python runnable title="Dividing in place, whole numbers only"
students = 17
students //= 5

print(students)
```

### Modulus and Assign (%=)

```python runnable title="Keeping only the leftover"
students = 17
students %= 5

print(students)
```

### Exponent and Assign (**=)

```python runnable title="Raising in place"
side = 4
side **= 2

print(side)
```

<div className="tscroll">

| Operator | Short for | Example | Result |
|---|---|---|---|
| `+=` | `x = x + y` | `78 += 5` | `83` |
| `-=` | `x = x - y` | `3 -= 1` | `2` |
| `*=` | `x = x * y` | `40 *= 2` | `80` |
| `/=` | `x = x / y` | `450 /= 6` | `75.0` |
| `//=` | `x = x // y` | `17 //= 5` | `3` |
| `%=` | `x = x % y` | `17 %= 5` | `2` |
| `**=` | `x = x ** y` | `4 **= 2` | `16` |

</div>

## Logical Operators

Logical operators combine yes-or-no answers into one yes-or-no answer.

### and

`and` returns `True` only when both conditions on the left and right are `True`.

```python runnable title="Both must be true"
maths = 78
science = 85
PASS_MARK = 35

print(maths >= PASS_MARK and science >= PASS_MARK)
print(maths >= PASS_MARK and 20 >= PASS_MARK)
```

The first line is `True` because both subjects passed. The second is `False` because one did not.

### or

`or` returns `True` when at least one condition on the left or right is `True`.

```python runnable title="One is enough"
maths = 78
science = 20
PASS_MARK = 35

print(maths >= PASS_MARK or science >= PASS_MARK)
print(20 >= PASS_MARK or 15 >= PASS_MARK)
```

### not

`not` reverses a `True` answer to `False`, or a `False` answer to `True`.

```python runnable title="Flipping the answer"
passed = True

print(not passed)
print(not 20 >= 35)
```

### Boolean Expressions

Combine them and you can describe a real rule in one line.

```python runnable title="A rule written out"
maths = 78
science = 85
attendance = 92

PASS_MARK = 35
MIN_ATTENDANCE = 75

promoted = maths >= PASS_MARK and science >= PASS_MARK and attendance >= MIN_ATTENDANCE

print("Promoted:", promoted)
```

Read it aloud and it is the school rule, word for word.

### Short-Circuit Evaluation

Python stops reading as soon as it knows the answer. This is called **short-circuit evaluation**.

With `and`, if the left side is `False`, the whole thing is `False`, so the right side is never looked at.

```python runnable title="The right side is never reached"
subjects = 0

if subjects != 0 and 450 / subjects > 50:
    print("Average is above 50")
else:
    print("No subjects to divide by")
```

`subjects != 0` is `False`, so Python never works out `450 / subjects`. Without that check on the left, the program would stop with a `ZeroDivisionError`.

This is not a trick. Putting the safe test on the left of an `and` is how real Python code avoids this kind of error.

Put the test that protects the other one on the left: `if subjects != 0 and total / subjects > 50`. Python reads left to right and stops early, so the dangerous half never runs.

## Conditional Expression (Ternary Operator)

### What Is a Conditional Expression?

A **conditional expression** chooses between two values in one line.

```text
value_if_true if condition else value_if_false
```

The condition sits in the middle. Read it as a sentence: *this value, if the test is true, otherwise that value.*

```python runnable title="Choosing a value in one line"
marks = 78
PASS_MARK = 35

result = "Pass" if marks >= PASS_MARK else "Fail"

print(result)
```

The same thing written as an `if` statement takes four lines:

```python runnable title="The same choice, the long way"
marks = 78
PASS_MARK = 35

if marks >= PASS_MARK:
    result = "Pass"
else:
    result = "Fail"

print(result)
```

Both are correct. Use the one-line form when the choice is small enough to read at a glance, and the `if` statement when there is more to do in each branch.

## Identity Operators

Identity operators ask whether two names refer to the exact same object. This is different from checking whether the values inside are equal.

### is

`is` checks whether two names refer to the exact same object.

```python runnable title="Same value, different objects"
first = [78, 85]
second = [78, 85]
third = first

print(first == second)
print(first is second)
print(first is third)
```

`first == second` is `True`: the two lists hold the same values. `first is second` is `False`: they are two separate lists that happen to hold matching values. `first is third` is `True`, because `third` is another name for the very same list.

### is not

`is not` checks whether two names point to different objects in memory.

```python runnable title="Not the same object"
first = [78, 85]
second = [78, 85]

print(first is not second)
```

### Identity vs Equality

Think of it like this: two names can point at two different boxes that hold the same things, or at one single box with two labels. `==` compares what is inside the boxes. `is` asks whether there is only one box.

Why it matters: if two names point at the same list, changing it through one name changes what you see through the other.

```python runnable title="One list, two names"
first = [78, 85]
third = first

third.append(60)

print(first)
print(third)
```

You appended to `third` and `first` changed too, because there was only ever one list.

### Comparing Object Identity

The one place you should always use `is` is `None`.

```python runnable title="The right way to test for None"
remark = None

print(remark is None)
print(remark is not None)
```

A running Python program has only one `None`, so `is None` is exactly the right question. It is also the form every Python programmer writes, so other readers expect it.

Use `==` to compare values, which is almost always what you want. Use `is` only for `None`, or when you really are asking whether two names point at one object.

## Membership Operators

Membership operators ask whether a value exists inside a collection, like a list, tuple, or string. They give `True` or `False` as the answer.

### in

`in` checks whether a value exists inside a collection.

```python runnable title="Is it in the list?"
marks = [78, 85, 60]

print(78 in marks)
print(90 in marks)
```

### not in

`not in` checks whether a value does not exist inside a collection.

```python runnable title="Is it absent?"
marks = [78, 85, 60]

print(90 not in marks)
```

### Membership Testing in Strings

With text, `in` looks for a smaller piece inside a bigger one.

```python runnable title="Looking inside text"
remark = "Good work this term"

print("work" in remark)
print("Work" in remark)
```

The second is `False` because capital and small letters are different characters. Lowercase both sides when the difference does not matter:

```python runnable title="Ignoring the capitals"
remark = "Good work this term"

print("work" in remark.lower())
print("WORK".lower() in remark.lower())
```

### Membership Testing in Lists, Tuples, Sets, and Dictionaries

`in` works the same way on every kind of collection. On a dictionary it checks the keys.

```python runnable title="The same question, four kinds of collection"
marks_list = [78, 85, 60]
marks_tuple = (78, 85, 60)
marks_set = {78, 85, 60}
report = {"maths": 78, "science": 85}

print(78 in marks_list)
print(78 in marks_tuple)
print(78 in marks_set)
print("maths" in report)
print(78 in report)
```

The last line is `False`. On a dictionary, `in` looks at the keys, and 78 is a value. `78 in report.values()` is the question that gives `True`.

The next two sections cover operators that beginners use less often. You do not need to memorize them right now, but it is useful to know they exist because you may see them in real Python code.

## Bitwise Operators

Every whole number is stored as bits: a row of 1s and 0s. Bitwise operators work on those bits one position at a time.

You will not need these often as a beginner. They matter for permissions, flags and some hardware work, so it is worth knowing they exist.

The number 12 is `1100` in bits, and 10 is `1010`.

### Bitwise AND (&)

`&` compares the bits of two numbers and keeps only the bits that are 1 in both.

```python runnable title="AND on the bits"
print(bin(12), bin(10))
print(12 & 10)
print(bin(12 & 10))
```

`1100` and `1010` share a 1 only in the third position, which gives `1000`, and that is 8.

### Bitwise OR (|)

`|` compares the bits of two numbers and keeps a bit if it is 1 in either number.

```python runnable title="OR on the bits"
print(12 | 10)
print(bin(12 | 10))
```

### Bitwise XOR (^)

`^` compares the bits of two numbers and keeps a bit only if it is 1 in exactly one of them.

```python runnable title="XOR on the bits"
print(12 ^ 10)
print(bin(12 ^ 10))
```

### Bitwise NOT (~)

`~` flips every bit in a number. For whole numbers this works out as `-(n + 1)`.

```python runnable title="Flipping every bit"
print(~12)
print(~0)
```

<div className="tscroll">

| Operator | Name | `12` and `10` | Result |
|---|---|---|---|
| `&` | AND | `1100` `1010` | `8` |
| `\|` | OR | `1100` `1010` | `14` |
| `^` | XOR | `1100` `1010` | `6` |
| `~` | NOT | `1100` | `-13` |

</div>

`&` is not `and`. `&` works on the bits inside two numbers. `and` combines two yes-or-no answers. Using one where you meant the other gives an answer that looks almost right.

## Walrus Operator

### What Is the Walrus Operator?

The **walrus operator** `:=` stores a value in a name and gives that value back at the same time.

It is called the walrus because `:=` looks like a walrus lying on its side, with two eyes and a tusk.

### Assignment Expressions

A normal `=` line does its job but gives nothing back to the rest of the line. `:=` is different: it stores the value and hands it back, so you can use it straight away.

```python runnable title="Store it and use it at once"
remark = "Good work this term"

if (length := len(remark)) > 10:
    print("Long remark:", length, "characters")
```

`len(remark)` was worked out once, stored in `length`, and used in the test and in the message.

### Using the Walrus Operator in Conditions

Without the walrus you have to call the function twice, or add a line above.

```python runnable title="The same thing without it"
remark = "Good work this term"

length = len(remark)
if length > 10:
    print("Long remark:", length, "characters")
```

Both are fine. The walrus form keeps the value next to the test that uses it.

### Benefits of the Walrus Operator

- The work is done once, not twice.
- The name is created right where it is needed.
- The loop or test stays on one line.

```python runnable title="Keeping only the marks worth reporting"
marks = [78, 20, 85, 12, 60]
good = [doubled for mark in marks if (doubled := mark * 2) > 100]

print(good)
```

Each mark was doubled once. The doubled value was tested, and the same value was kept.

Use it when it makes a line clearer. A plain extra line above is never wrong.

## Operator Precedence

### What Is Operator Precedence?

**Precedence** is the order Python applies operators in when a line has several.

```python runnable title="Which operator goes first?"
print(2 + 3 * 4)
```

The answer is 14, not 20. `*` is applied before `+`, exactly as in mathematics.

### Order of Operator Evaluation

From first applied to last:

<div className="tscroll">

| Order | Operators | Group |
|---|---|---|
| 1 | `()` | brackets |
| 2 | `**` | power |
| 3 | `-x` `~x` | sign, bitwise not |
| 4 | `*` `/` `//` `%` | multiply and divide |
| 5 | `+` `-` | add and subtract |
| 6 | `&` `^` `\|` | bitwise |
| 7 | `==` `!=` `>` `<` `>=` `<=` `is` `in` | comparisons |
| 8 | `not` | logical not |
| 9 | `and` | logical and |
| 10 | `or` | logical or |

</div>

Two things are worth taking from that table. Comparisons happen **after** all the arithmetic, which is why `marks + 5 >= 35` works without brackets. And `and` happens before `or`.

### Using Parentheses

Brackets beat everything — whatever is inside them is worked out first. They are also the only part of this table nobody has to remember.

```python runnable title="Brackets change the answer"
print(2 + 3 * 4)
print((2 + 3) * 4)
```

Same numbers, same operators, different answers: 14 and 20.

### Precedence Examples

Here is where precedence quietly changes a result:

```python runnable title="and before or"
maths = 78
science = 85
attendance = 50

print(maths >= 35 or science >= 35 and attendance >= 75)
print((maths >= 35 or science >= 35) and attendance >= 75)
```

The first line is `True`, the second `False`. Python applied `and` first, so the first line really asks: did maths pass, **or** did both science and attendance pass? The brackets in the second line ask the school's actual rule instead.

Nothing was wrong with Python here. The line was ambiguous to a human and precise to Python, so it is exactly the kind of line where brackets help.

When a line mixes `and` with `or`, add brackets even where Python does not need them. The brackets cost nothing and they say what you meant.

## Common mistakes

Each row is one mistake. The middle column is what you will actually see on screen.

<div className="tscroll">

| Mistake | What you see | Why it happens | Fix |
|---|---|---|---|
| Using `=` where you meant `==` | `SyntaxError: invalid syntax` | One `=` stores a value; a test needs two | `if marks == 78:` |
| Expecting `/` to give a whole number | `10 / 2` shows `5.0` | `/` always gives a decimal | Use `//` when the fraction makes no sense |
| Dividing by a value that can be zero | `ZeroDivisionError: division by zero` | Nothing checked the divisor first | Guard it: `if subjects != 0 and ...` |
| Mixing `and` with `or` and no brackets | An answer that is right for Python and wrong for you | `and` is applied before `or` | Add brackets around the part you mean |
| Using `is` to compare values | `False` for two lists that look identical | `is` asks whether there is one object, not two equal ones | Use `==` for values; keep `is` for `None` |
| Changing a list through a second name | A list you never touched has changed | Both names point at one list | Copy it first: `second = first.copy()` |
| Using `&` where you meant `and` | A number instead of `True` or `False` | `&` works on bits inside numbers | Use `and` for yes-or-no answers |
| Searching text with the wrong case | `"Work" in remark` is `False` | Capital and small letters are different characters | Lowercase both sides first |
| Expecting `in` to search a dictionary's values | `78 in report` is `False` | On a dictionary, `in` looks at the keys | `78 in report.values()` |
| Forgetting `%` needs a whole-number mindset | A leftover you did not expect | `%` gives the remainder, not the share | `17 // 5` is the share, `17 % 5` the leftover |

</div>

## What to Remember

- **An operator takes values and produces a new value.** The values are operands; the whole thing is an expression.
- `/` always gives a decimal. `//` gives the whole part, and `%` gives what is left over.
- `**` raises to a power, and `** 0.5` is the square root.
- One `=` stores. Two `==` ask a question.
- Comparisons produce `True` or `False`, and Python lets you chain them: `35 <= marks <= 100`.
- `+=` and the rest update a variable in place.
- `and` needs both sides; `or` needs one; `not` flips the answer.
- **Python stops reading as soon as it knows the answer**, so the left side of an `and` can protect the right.
- `value_if_true if condition else value_if_false` chooses between two values in one line.
- `==` compares values. `is` asks whether two names point at one object — keep it for `None`.
- `in` asks whether a value is inside a collection, and on a dictionary it looks at the keys.
- `&` `|` `^` `~` work on the bits inside numbers, and are not the same as `and` and `or`.
- `:=` stores a value and gives it back in the same line.
- **Brackets beat every rule of precedence**, and they say what you meant.

Next: **Conditional Statements**
