Data Handling is the chapter that systematically explores the data types Python offers, how values are stored, how they can be converted from one type to another, and how the standard library extends Python's capabilities. Every program processes data, and choosing the correct data type for a piece of information is one of the first decisions a programmer makes. A wrong choice can lead to wasted memory, incorrect results, or both. This chapter therefore builds a deep understanding of Python's built-in types, their properties, and their mutability.
Python supports several core data types: integers (int), floating-point numbers (float), complex numbers, strings (str), booleans (bool) and the special value None. Beyond these, Python provides sequence and mapping types such as lists, tuples and dictionaries, which will be studied in later chapters. An important concept introduced here is mutability: some types can be changed after creation (mutable), while others cannot (immutable). Understanding which types are immutable is crucial for avoiding subtle bugs, especially when passing values to functions.
The chapter also covers type conversion between data types, the operators that work with each type, and two of the most useful standard library modules: math and random. These modules save programmers from writing common mathematical and random-number routines from scratch and illustrate the power of Python's "batteries included" philosophy, where the standard library comes with a rich set of pre-written, tested modules.
Python's built-in data types can be grouped as follows:
Each type has its own set of supported operations. For example, the + operator adds numbers but concatenates strings; the * operator multiplies numbers but repeats strings.
Integers are whole numbers, positive or negative, without a decimal point, such as -5, 0, 1000000. In Python 3, integers have arbitrary precision, meaning they can be as large as memory allows. Integer literals can be written in decimal, binary (0b prefix), octal (0o prefix) or hexadecimal (0x prefix).
Floats are numbers with a fractional part, such as 3.14, -0.5, 2.0, and can also be written using scientific (exponent) notation: 2.5e3 means 2500.0 and 1e-3 means 0.001. Floats are stored according to the IEEE 754 standard, so some decimal fractions like 0.1 are stored only approximately.
Complex numbers have a real and an imaginary part, written like 3 + 4j, where j is the imaginary unit. They are used in scientific and engineering calculations.
a = 10 # int
b = 3.14 # float
c = 2 + 5j # complex
print(a + b) # 13.14
print(c.real, c.imag) # 2.0 5.0
A string is a sequence of characters enclosed in single, double or triple quotes. Strings in Python are immutable, meaning that once a string is created, its characters cannot be changed; any operation that appears to modify a string actually creates a new string. Strings support indexing (getting a single character), slicing (getting a substring) and the + and * operators.
name = "Python"
print(name[0]) # 'P'
print(name[-1]) # 'n'
print(name[1:4]) # 'yth'
print("Py" + "thon") # 'Python'
print("ha" * 3) # 'hahaha'
The boolean type has exactly two values, True and False, which are the result of comparisons and logical operations. In Python, booleans behave like integers in some contexts: True is 1 and False is 0. This is why True + True is 2. Booleans are heavily used in conditions for if statements and loops.
passed = True
failed = False
print(True + True) # 2
print(int(passed)) # 1
This is a central concept of Python data handling.
For example, an integer operation creates a new integer object rather than changing the existing one. Strings are immutable too; the statement s[0] = 'x' raises a TypeError. Lists, on the other hand, can be modified in place, for example by assigning to an index.
s = "hello"
# s[0] = 'H' # Error: strings are immutable
lst = [1, 2, 3]
lst[0] = 99 # Allowed: lists are mutable
print(lst) # [99, 2, 3]
Understanding mutability is important because when a mutable object is shared (for example, passed to a function), changes made inside the function affect the original object, whereas immutable objects are effectively copied on change.
Python can convert values between data types using built-in functions. Conversion can be:
print(5 + 2.5) # 7.5 (implicit)
print(int(7.9)) # 7 (truncates, not rounds)
print(float(3)) # 3.0
print(str(42)) # '42'
print(complex(2, 3)) # (2+3j)
Some conversions fail. Converting a non-numeric string like int("hello") raises a ValueError, and converting a string with a decimal point to int, int("3.14"), also raises a ValueError. Truncation vs rounding is a common confusion: int(7.9) is 7, not 8.
Python's standard library includes the math module with many mathematical functions and constants. To use it, the module is first imported with the import statement.
import math
print(math.pi) # 3.141592653589793
print(math.sqrt(16)) # 4.0
print(math.floor(7.8)) # 7
print(math.ceil(7.2)) # 8
print(math.pow(2, 5)) # 32.0
print(math.fabs(-4.5)) # 4.5
print(math.factorial(5)) # 120
Common functions include sqrt, pow, floor, ceil, fabs, factorial, gcd, and trigonometric functions such as sin, cos and tan. Constants pi and e are also provided.
The random module is used to generate random numbers and make random choices. These capabilities are used in games, simulations and sampling.
import random
print(random.random()) # float in [0.0, 1.0)
print(random.randint(1, 6)) # integer between 1 and 6 inclusive
print(random.randrange(1, 10, 2)) # odd number from 1,3,5,7,9
print(random.choice(["a", "b", "c"])) # random element
lst = [1, 2, 3, 4, 5]
random.shuffle(lst) # shuffles the list in place
print(lst)
randint(a, b) returns an integer in the inclusive range a to b, while randrange is used with step values. random() returns a float between 0 (inclusive) and 1 (exclusive).
import random
secret = random.randint(1, 10)
guess = int(input("Guess a number between 1 and 10: "))
if guess == secret:
print("You won!")
else:
print("Wrong! The number was", secret)
import math
r = float(input("Enter radius: "))
area = math.pi * r ** 2
circumference = 2 * math.pi * r
print("Area:", round(area, 2))
print("Circumference:", round(circumference, 2))
| Type | Example | Mutable? | Description |
|---|---|---|---|
| int | 42 | No | Whole numbers |
| float | 3.14 | No | Numbers with decimals |
| complex | 2+3j | No | Real and imaginary parts |
| str | "Hi" | No | Sequence of characters |
| bool | True | No | True or False |
| list | [1,2] | Yes | Ordered, changeable sequence |
| tuple | (1,2) | No | Ordered, unchangeable sequence |
| dict | {"a":1} | Yes | Key-value pairs |
| Function | Module | Result |
|---|---|---|
| sqrt(x) | math | Square root of x |
| floor(x) | math | Largest integer <= x |
| ceil(x) | math | Smallest integer >= x |
| factorial(n) | math | n! product |
| random() | random | Float in [0.0, 1.0) |
| randint(a, b) | random | Integer in [a, b] |
| choice(seq) | random | Random element of seq |
Data Handling transforms the simple building blocks of the previous chapter into a full understanding of Python's type system. Integers, floats, complex numbers, strings, booleans and None each have their own characteristics, and the crucial distinction between mutable and immutable types governs how values behave in memory. Type conversion, both implicit and explicit, allows values to move between types safely when done correctly. The math and random modules demonstrate how Python's standard library provides ready-made, powerful tools. With data and its handling mastered, the next chapter explores how to control the flow of a program using conditions and loops, enabling programs to make decisions and repeat actions.