Chapter 03 of 24 | Python

Values, types, and variables

Every Python object has a type and a value. A name is a label bound to an object; assignment binds or rebinds a name rather than declaring a permanent storage box with a fixed type.

count = 3
price = 2.50
title = "Notebook"
is_available = True
print(type(count), type(price), type(title), type(is_available))

Common built-in types include integers (int), floating-point numbers (float), text (str), Booleans (bool), and None for the absence of a value. Integers can grow beyond fixed machine-word ranges, while floats use finite-precision binary arithmetic.

Assignment, identity, and equality

first = [1, 2]
second = first
second.append(3)
print(first)          # [1, 2, 3]
print(first is second)  # True: same object
print(first == second)  # True: equal contents

Assignment does not copy a mutable object. Both names above refer to the same list. Equality (==) asks whether values compare equal; identity (is) asks whether two references denote the same object. Use is None to test for the singleton None, not as a general substitute for equality.

Mutability and copying

Strings, integers, and tuples are immutable: an operation that appears to change them creates or returns a different value. Lists, dictionaries, and sets are mutable. A shallow copy duplicates the outer container but still shares nested objects; copy.deepcopy recursively copies many nested structures, but may be inappropriate for resources or objects with custom identity.

import copy

original = [[1], [2]]
shallow = original.copy()
shallow[0].append(9)
print(original)  # the inner list is shared
independent = copy.deepcopy(original)

Conversions and numeric precision

whole = int("42")
ratio = float("3.5")
text = str(whole)
print(0.1 + 0.2)  # binary floating-point approximation

Conversions can fail, such as int("hello"), or lose information, such as int(3.9), which truncates toward zero. For money, consider integer cents or decimal.Decimal rather than relying on binary floating-point equality. Use math.isclose for approximate comparisons when that matches the domain.

Type hints: documentation, not runtime enforcement

def repeat_label(label: str, count: int) -> list[str]:
    return [label] * count

Annotations help readers, editors, and static type checkers understand intended types. Python normally does not enforce them automatically while running. A type checker can find many mismatches before execution, but its result depends on annotations, configuration, and the code it can analyze.

Beginner-to-master progression

Exercises

  1. Predict the output when two names refer to one list, then compare it with two independent copies.
  2. Demonstrate why 0.1 + 0.2 == 0.3 may be false and choose an appropriate comparison for a measurement.
  3. Add annotations to a small function and run a type checker if one is available.

Hashability and dictionary keys

Dictionary keys and set elements must be hashable. A hashable object's hash and equality behavior must remain stable while it is used as a key. Immutable built-in values such as strings and integers are common keys; a list is mutable and unhashable. A tuple is hashable only when all its elements are hashable.

locations = {(51.5, -0.1): "London"}
print(locations[(51.5, -0.1)])
# locations[[51.5, -0.1]] would raise TypeError

Custom classes that define equality need a consistent hash policy if instances are to be dictionary keys. Equal objects must have equal hashes. Mutable objects whose equality-relevant fields can change are poor keys because changing them can make dictionary lookup inconsistent with their stored bucket.

Domain modeling and exact values

Use a domain-specific type when primitive values are easy to confuse. A distance in meters and a duration in seconds may both be floats, but adding them is meaningless. A small immutable dataclass or validated wrapper can make units explicit. For monetary calculations, Decimal supports decimal arithmetic, but construction from strings is preferable to construction from an already-rounded float.

from decimal import Decimal

unit_price = Decimal("0.10")
quantity = 3
total = unit_price * quantity
print(total)

Choose precision, rounding mode, and quantization rules according to the domain. Decimal arithmetic is not automatically “correct” for every financial policy; the application's rules must still define how and when values are rounded.

Mastery checkpoint

  1. Design a hashable immutable value object and test equality/hash consistency.
  2. Compare float, integer-minor-unit, and Decimal representations for a financial calculation.
  3. Use a static type checker to find a function call that passes the wrong kind of value, then explain why runtime annotations alone would not reject it.
0% read