Python Operators Explained: Arithmetic, Comparison, Logical, and Beyond

An operator in Python is a symbol — or occasionally a keyword — that performs an operation on one or more values. The values an operator acts on are called operands. When you write `3 + 4`, the `+` is the operator and `3` and `4` are the operands. That single idea sits underneath every expression you will ever write, from a simple counter increment to a tensor multiplication.

The reason Python operators trip up so many otherwise competent developers is not that the symbols are hard. It is that several of them look similar, behave differently across types, and a couple of them ask subtly different questions that happen to give the same answer most of the time — right up until they don’t. This guide walks through every operator category with runnable code and output, then drills into the precedence rules and the `is` versus `==` trap that produces some of the most frustrating bugs in the language.

[!NOTE]
Key Takeaways
• An operator is a symbol or keyword that performs an operation on operands; Python groups them into arithmetic, comparison, logical, assignment, bitwise, membership, and identity categories.
• Use `==` to compare values (what you almost always want); reserve `is` for identity checks against singletons like `None`.
• `/` always returns a float; `//` does floor division; `` is exponentiation — three of the most commonly confused arithmetic operators in Python**.
Logical operators in Python (`and`, `or`, `not`) short-circuit and return one of the operands, not necessarily a bare `True`/`False`.
• Python supports chained comparisons like `1 < x < 10`, evaluated the way mathematics reads them.

What exactly is an operator in Python?

An operator connects operands into an expression that evaluates to a value. Operators fall into two structural groups: binary operators that take two operands (`a + b`), and unary operators that take one (`-a`, `not a`). Most operators are symbols, but Python also exposes a handful as keywords — `and`, `or`, `not`, `in`, and `is` — because reading `a and b` is clearer than any punctuation would be.

Under the hood, operators are method calls. When you write `a + b`, Python invokes `a.__add__(b)`. This is why the same `+` adds integers, concatenates strings, and merges lists — each type defines its own behavior. That mechanism, operator overloading, is what makes Python feel consistent across wildly different data structures.

“`python print(3 + 4) # 7 -> integer addition print(“Da” + “raz”) # Daraz -> string concatenation print([1, 2] + [3, 4]) # [1, 2, 3, 4] -> list concatenation “`

The operator did not change; the type of the operands decided the operation. Keep that in mind as you read on — every category below ultimately resolves to a method on the operand’s type.

What are the arithmetic operators in Python?

Arithmetic operators do the math you expect, with two important surprises around division. The table below lists all seven.

Operator Name Example Result
`+` Addition `7 + 2` `9`
`-` Subtraction `7 – 2` `5`
`*` Multiplication `7 * 2` `14`
`/` True division `7 / 2` `3.5`
`//` Floor division `7 // 2` `3`
`%` Modulo (remainder) `7 % 2` `1`
`**` Exponentiation `7 ** 2` `49`

The trap is `/` versus `//`. In Python 3, `/` always returns a float, even when the operands divide evenly. Floor division `//` rounds toward negative infinity and returns an int (when both operands are ints).

“`python print(7 / 2) # 3.5 -> true division, always a float print(7 // 2) # 3 -> floor division, drops the fractional part print(10 / 2) # 5.0 -> still a float, note the .0 print(-7 // 2) # -4 -> floors toward negative infinity, not zero print(7 % 3) # 1 -> remainder print(2 ** 10) # 1024 -> exponentiation “`

That `-7 // 2 == -4` result surprises people who expect truncation toward zero. Python floors, so it rounds down to `-4`, not `-3`. The companion behavior is in `%`, which always returns a result with the same sign as the divisor. For a deeper treatment of these two together, see the dedicated walkthrough below in the internal links.

What are the comparison operators in Python?

Comparison operators evaluate a relationship between two operands and return a boolean. These are the engine behind every `if` statement and `while` loop you write.

Operator Meaning Example Result
`==` Equal to `5 == 5` `True`
`!=` Not equal to `5 != 4` `True`
`>` Greater than `5 > 4` `True`
`<` Less than `5 < 4` `False`
`>=` Greater than or equal `5 >= 5` `True`
`<=` Less than or equal `4 <= 5` `True`

“`python print(5 == 5.0) # True -> value equality across int and float print(“abc” == “abc”) # True -> string comparison is value-based print(3 != 4) # True print([1, 2] == [1, 2]) # True -> lists compare element by element print(2 < 5 <= 5) # True -> chained comparison, more below “`

Notice `5 == 5.0` is `True`. The `==` operator compares values, and Python considers the integer 5 and the float 5.0 numerically equal even though their types differ. Hold that thought — it becomes the centerpiece of the `is` versus `==` discussion later.

Can you chain comparisons in Python?

Yes, and this is one of Python’s genuinely elegant features. You can write a range check the way you would on paper:

“`python x = 7 print(1 < x < 10) # True -> reads as “is x between 1 and 10?” print(1 < x < 5) # False ```

Python evaluates `1 < x < 10` as `(1 < x) and (x < 10)`, but it evaluates `x` only once. In most other languages `1 < x < 10` would compare `1 < x` to get a boolean, then compare that boolean to `10` — a silent bug. Python does the mathematically correct thing.

How do logical operators work in Python?

The logical operators in Python are the keywords `and`, `or`, and `not`. They combine boolean expressions, and two of them have a behavior that catches newcomers: they short-circuit and return an operand, not necessarily a literal `True` or `False`.

Operator Behavior Example Result
`and` True if both operands are truthy `True and False` `False`
`or` True if either operand is truthy `True or False` `True`
`not` Inverts the truth value `not True` `False`

“`python print(True and False) # False print(True or False) # True print(not True) # False

def expensive(): print(“called!”) return True

result = False and expensive() # expensive() never runs print(result) # False “`

The detail that surprises people is what `and`/`or` actually return:

“`python print(3 and 5) # 5 -> returns the last operand when all are truthy print(0 or “fallback”) # fallback -> returns the first truthy operand print(None or 0 or []) # [] -> returns the last when all are falsy “`

`and` returns the first falsy operand or the last operand; `or` returns the first truthy operand or the last operand. This is why `name or “Anonymous”` is such a common idiom for defaults — it falls through to the fallback only when `name` is falsy.

What are assignment operators in Python?

The plain `=` assigns a value to a name. The augmented assignment operators combine an arithmetic or bitwise operation with assignment, so `x += 1` means `x = x + 1`.

Operator Equivalent Operator Equivalent
`+=` `x = x + y` `//=` `x = x // y`
`-=` `x = x – y` `%=` `x = x % y`
`*=` `x = x * y` `**=` `x = x ** y`
`/=` `x = x / y` `&=` ` =` `^=` bitwise in place

“`python x = 10 x += 5 # x is now 15 x -= 3 # x is now 12 x *= 2 # x is now 24 x //= 5 # x is now 4 print(x) # 4

total = 0 for n in [1, 2, 3, 4]: total += n # accumulate print(total) # 10 “`

For mutable types, augmented assignment can behave in place. `list += other` extends the existing list object rather than creating a new one — a distinction that occasionally matters when the list is shared by reference.

What are bitwise operators in Python?

Bitwise operators act on the binary representation of integers, bit by bit. You will reach for these less often in everyday application code, but they are essential for flags, permissions, low-level protocols, and performance-sensitive work.

Operator Name Example Binary view Result
`&` AND `6 & 3` `110 & 011` `2`
` ` OR `6 3` `110 011` `7`
`^` XOR `6 ^ 3` `110 ^ 011` `5`
`~` NOT (invert) `~6` invert bits `-7`
`<<` Left shift `6 << 1` shift left `12`
`>>` Right shift `6 >> 1` shift right `3`

“`python print(6 & 3) # 2 -> 110 & 011 = 010 print(6 | 3) # 7 -> 110 | 011 = 111 print(6 ^ 3) # 5 -> 110 ^ 011 = 101 print(~6) # -7 -> ~x equals -(x + 1) print(6 << 1) # 12 -> shifting left by 1 doubles the value print(6 >> 1) # 3 -> shifting right by 1 halves it (floored)

READ, WRITE, EXEC = 1, 2, 4 perms = READ | WRITE # combine flags print(perms & WRITE) # 2 -> truthy, WRITE is set print(bool(perms & EXEC)) # False -> EXEC is not set “`

The flag pattern above is worth memorizing. `|` sets flags, `&` tests them. That single technique replaces a tangle of booleans with one integer.

What are membership and identity operators in Python?

Two keyword pairs round out the set. Membership operators test whether a value appears in a container; identity operators test whether two names refer to the same object.

Category Operator Question it asks
Membership `in` Is this value present in the container?
Membership `not in` Is this value absent from the container?
Identity `is` Are these the exact same object in memory?
Identity `is not` Are these different objects?

“`python fruits = [“apple”, “banana”, “cherry”] print(“banana” in fruits) # True print(“grape” not in fruits) # True print(“ana” in “banana”) # True -> substring check on strings print(3 in {“a”: 1, 3: “x”}) # True -> checks keys for dicts

a = [1, 2, 3] b = a # same object c = [1, 2, 3] # equal value, different object print(a is b) # True -> b points to the same list as a print(a is c) # False -> c is a separate object print(a == c) # True -> but their values are equal “`

That final block is the crux of the most important distinction in this entire guide.

The operator that causes the most subtle Python bugs is `is` versus `==` — because they look interchangeable but ask different questions. `==` asks “are these two values equal?” while `is` asks “are these the exact same object in memory?” They often agree for small integers and interned strings, which Python caches behind the scenes, and that coincidence lulls developers into using `is` for value comparison. It works in the REPL, it works in tests, and then it silently fails on a larger value or a freshly constructed object. Two equal lists are `==` but not `is`. The rule that prevents the bug is simple: use `==` to compare values (almost always what you want), and reserve `is` for comparing against singletons like `None` (`if x is None:`). “Equal” and “identical” are different questions; pick the operator that asks the one you actually mean.

“`python

x = 256 print(x is 256) # True in CPython -> small ints are cached y = 257 print(y is 257) # often False -> outside the cached range, fresh object

print(y == 257) # True -> correct, type- and version-independent

value = None if value is None: # correct: None is a singleton print(“no value”) # no value “`

How does operator precedence work in Python?

When an expression mixes operators, precedence decides what evaluates first. Python follows the familiar mathematical ordering: exponentiation binds tightest, then unary minus, then `*` `/` `//` `%`, then `+` `-`, then comparisons, then `not`, then `and`, then `or`. Within the same precedence level, most operators are left-associative, but `**` is right-associative.

“`python print(2 + 3 * 4) # 14 -> * before +, not 20 print(2 3 2) # 512 -> right-associative: 2 (3 2) print((2 + 3) * 4) # 20 -> parentheses override precedence print(not True or True)# True -> not binds tighter than or “`

The pragmatic advice from someone who has debugged plenty of these: do not try to memorize the full precedence table for production code. Use parentheses to make intent explicit. `(a and b) or c` reads unambiguously; `a and b or c` makes a reviewer pause. Parentheses cost nothing and remove an entire class of misreadings.


Run Python the way you control it. DarazHost VPS and dedicated servers give developers a real Python environment with full control — install any Python version you need, run scripts and long-lived apps, and build on guaranteed resources with root access. It is the dependable home your Python work deserves, backed by 24/7 support, so the only thing you debug is your code — not your hosting. If you are moving past local experiments toward something that has to stay up, that environment matters.


These operator rules are the same whether you run code on your laptop or a production server, but where you run it shapes how confidently you can test edge cases like the `is`/`==` behavior across Python versions. For the bigger picture on owning your runtime, read the complete guide to a real development environment you control, which covers how full control over your stack changes the way you build.

If you are still finding your footing with the language itself, the fundamentals come first.

Frequently asked questions about Python operators

What is the difference between `=` and `==` in Python? `=` is the assignment operator; it binds a value to a name (`x = 5`). `==` is the comparison operator; it tests whether two values are equal and returns a boolean (`x == 5`). Using `=` where you meant `==` is a syntax error inside an `if` condition in Python, which is one of the few times the language saves you from this classic mistake automatically.

When should I use `is` instead of `==`? Use `is` only when you genuinely need to know whether two names point to the same object — in practice, almost exclusively for checking against singletons like `None`, `True`, and `False` (`if x is None`). For comparing values, always use `==`. Relying on `is` for numbers or strings works by accident due to caching and breaks unpredictably.

Why does `7 / 2` return `3.5` instead of `3` in Python? In Python 3, the `/` operator always performs true division and returns a float, regardless of whether the operands divide evenly. If you want integer floor division, use `//` (`7 // 2` gives `3`). This was a deliberate change from Python 2, where `/` between two integers truncated.

What does `and` actually return in Python? `and` returns the first falsy operand it encounters, or the last operand if all are truthy — not necessarily a literal `True` or `False`. Similarly, `or` returns the first truthy operand. This short-circuit behavior powers idioms like `value = user_input or “default”`, which falls back only when `user_input` is falsy.

Are logical operators the same as bitwise operators? No. Logical operators (`and`, `or`, `not`) work on the truth value of whole expressions and short-circuit. Bitwise operators (`&`, `|`, `~`) operate on the individual bits of integers and always evaluate both operands. Writing `a & b` when you meant `a and b` can produce wrong results or errors, because `&` does not short-circuit and treats its operands as bit patterns.

About the Author

Leave a Reply