Chapter 05 of 24 | Python

Expressions and operators

An expression combines values, names, and operators to produce a value. Python supports arithmetic, comparisons, Boolean logic, membership tests, identity tests, and operations specific to types such as string concatenation.

subtotal = 19.95 * 3
tax = subtotal * 0.08
total = subtotal + tax
print(f"Total: ${total:.2f}")

Arithmetic and precedence

Python's arithmetic operators include addition (+), subtraction (-), multiplication (*), division (/), floor division (//), exponentiation (**), and remainder (%). Division with / produces a float; floor division rounds toward negative infinity, so -7 // 3 is -3, not -2. Parentheses make intended grouping clear.

Precedence determines grouping, but long expressions are often clearer as named intermediate values. Avoid expressions whose correctness depends on remembering many precedence levels. Floating-point operations can introduce rounding, and integer division by zero raises ZeroDivisionError.

Comparisons and chained comparisons

score = 84
passed = score >= 60
in_range = 0 <= score <= 100
is_weekend = day == "Saturday" or day == "Sunday"

Unlike many languages, Python supports mathematical-style chained comparisons such as 0 <= x <= 100. The middle expression is evaluated once. Comparisons can also chain accidentally in a way that does not match your intention, so use parentheses or separate variables when logic is complicated.

Boolean short-circuiting and truthiness

and and or short-circuit: the second operand may not be evaluated. They return one of their operands, not necessarily a Boolean. Empty strings and collections, zero, and None are false in a condition; most other objects are true.

username = ""
display_name = username or "Guest"
if records and records[0]["active"]:
    print("First record is active")

Use truthiness when “empty or absent” is the intended condition. Use an explicit comparison when zero, an empty collection, or None has a distinct meaning.

Augmented assignment and side effects

Operators such as += update a name or invoke an in-place operation. For immutable objects, the result is typically a new object; for mutable objects, an operation may modify the existing object. This distinction can affect aliases. Keep side effects out of complicated expressions so execution order remains easy to understand.

Beginner-to-master progression

Exercises

  1. Calculate the average of three values and avoid integer-like truncation assumptions.
  2. Write a range check using a chained comparison and test both boundaries.
  3. Create a small class that implements a meaningful comparison and explain the consistency rules it must follow.

Operator methods and reflected operations

When an operator is used with a user-defined object, Python may call special methods such as __add__ or __mul__. If the left operand cannot handle an operation, a reflected method such as __radd__ may be considered. Implement operator methods only when the operation has a natural meaning for the type.

Comparison methods should be coherent: equality should be symmetric in practice, and ordering should satisfy the assumptions made by sorting and ordered algorithms. Rich comparisons can return non-Boolean objects in specialized APIs, but ordinary domain types should usually return bool. Python does not automatically infer all comparison methods from one implementation unless a helper such as functools.total_ordering is deliberately applied.

Numeric protocols and precision traps

Python integers have arbitrary precision, so integer arithmetic does not wrap at a fixed machine width. This prevents many overflow errors but does not make huge integer calculations free: memory and processing time still grow with the number of digits. Floats are finite precision and follow the runtime's floating-point behavior. The decimal and fractions modules provide alternatives with different performance and exactness trade-offs.

from fractions import Fraction

exact = Fraction(1, 10) + Fraction(2, 10)
print(exact)  # 3/10

Constructing a fraction from a float captures that float's exact binary value, which may be a large fraction rather than the intended decimal. Prefer numerator/denominator integers or decimal text when exact rational intent matters.

Mastery checkpoint

  1. Implement a two-dimensional vector with addition and equality, then test algebraic properties.
  2. Show why equality, ordering, and hashing must agree when a value type is used in sets and sorted collections.
  3. Compare float, Decimal, and Fraction for one domain and justify the representation, rounding policy, and performance cost.
0% read