Section 3: Tuples
Tuples are like lists with a contract - once created, they can’t be modified. This immutability makes them perfect for storing coordinates, database records, or configuration settings that shouldn’t change during program execution. Think of tuples as the safety deposit box of Python data structures.
Introduction
Tuples are ordered collections of items that cannot be modified after creation. This immutability provides data integrity and makes tuples useful for storing related information that should remain constant, like coordinate pairs, RGB color values, or database records.
Creating Tuples
Tuples are defined using parentheses or by separating values with commas.
Basic Tuple Creation
# Method 1: Using parentheses
coordinates = (10, 20)
colors = ('red', 'green', 'blue')
mixed_data = ('Alice', 25, 75000, True)
# Method 2: Without parentheses (tuple packing)
point = 5, 15
person = 'Bob', 30, 'Engineer'
# Single-item tuple (note the comma)
single_item = (42,) # Comma is required
# Without comma, it's just parentheses for grouping
not_a_tuple = (42) # This is just an integer
print(f"Coordinates: {coordinates}")
print(f"Colors: {colors}")
print(f"Single item: {single_item}")
print(f"Type check: {type(single_item)}")Empty and Multiple Element Tuples
# Empty tuple
empty = ()
empty_alt = tuple()
# Multiple elements
dimensions = (1920, 1080, 32) # Width, height, color depth
rgb = (255, 128, 0) # Orange color
employee = ('Sarah', 'Manager', 85000, 'IT')
print(f"Empty tuple: {empty}")
print(f"Dimensions: {dimensions}")
print(f"RGB color: {rgb}")
print(f"Employee data: {employee}")Accessing Tuple Elements
Tuples support indexing and slicing like lists.
Indexing and Slicing
student_data = ('John Doe', 22, 'Computer Science', 3.8, True)
# Access individual elements
name = student_data[0]
age = student_data[1]
gpa = student_data[3]
print(f"Student: {name}")
print(f"Age: {age}")
print(f"GPA: {gpa}")
# Negative indexing
major = student_data[-3] # Third from the end
enrolled = student_data[-1] # Last element
print(f"Major: {major}")
print(f"Enrolled: {enrolled}")
# Slicing
personal_info = student_data[:2] # First two elements
academic_info = student_data[2:] # From third element onward
print(f"Personal: {personal_info}")
print(f"Academic: {academic_info}")Tuple Unpacking
# Unpack tuple into individual variables
coordinates = (45.5, -122.7)
latitude, longitude = coordinates
print(f"Latitude: {latitude}")
print(f"Longitude: {longitude}")
# Multiple assignment
employee = ('Alice Johnson', 'Developer', 75000)
name, position, salary = employee
print(f"Employee: {name}")
print(f"Position: {position}")
print(f"Salary: ${salary:,}")
# Swap variables using tuple unpacking
a = 10
b = 20
print(f"Before swap: a={a}, b={b}")
a, b = b, a # Elegant variable swap
print(f"After swap: a={a}, b={b}")Tuple Operations and Methods
While tuples are immutable, they support various operations and methods.
Basic Operations
numbers = (1, 2, 3, 4, 5)
letters = ('a', 'b', 'c')
# Length
print(f"Length of numbers: {len(numbers)}")
# Concatenation (creates new tuple)
combined = numbers + letters
print(f"Combined: {combined}")
# Repetition
repeated = ('echo',) * 3
print(f"Repeated: {repeated}")
# Membership testing
print(f"3 in numbers: {3 in numbers}")
print(f"'x' in letters: {'x' in letters}")
# Iteration
print("Iterating through numbers:")
for num in numbers:
print(f"Number: {num}")Tuple Methods
data = (1, 2, 3, 2, 4, 2, 5)
# count() - Count occurrences
count_2 = data.count(2)
print(f"Number of 2s: {count_2}")
# index() - Find first occurrence
index_of_4 = data.index(4)
print(f"Index of 4: {index_of_4}")
# Find index with start and end parameters
first_2 = data.index(2) # First occurrence
second_2 = data.index(2, 2) # First occurrence after index 1
print(f"First 2 at index: {first_2}")
print(f"Second 2 at index: {second_2}")Practical Applications
Tuples excel in scenarios requiring immutable data structures.
Database Records
# Represent database records as tuples
customers = [
(1, 'ABC Corp', 'alice@abc.com', '555-0101'),
(2, 'XYZ Ltd', 'bob@xyz.com', '555-0102'),
(3, 'Tech Inc', 'carol@tech.com', '555-0103')
]
print("Customer Database:")
print("ID | Company | Email | Phone")
print("-" * 40)
for customer_id, company, email, phone in customers:
print(f"{customer_id:2} | {company:8} | {email:14} | {phone}")
# Process specific customer
target_customer = customers[1]
cust_id, company, email, phone = target_customer
print(f"\nProcessing: {company} ({email})")Coordinates and Points
# Geographic coordinates
locations = [
('New York', 40.7128, -74.0060),
('London', 51.5074, -0.1278),
('Tokyo', 35.6762, 139.6503),
('Sydney', -33.8688, 151.2093)
]
def calculate_distance_info(locations):
"""Process geographic data."""
print("City Coordinates:")
for city, lat, lon in locations:
hemisphere_lat = 'N' if lat >= 0 else 'S'
hemisphere_lon = 'E' if lon >= 0 else 'W'
print(f"{city}: {abs(lat):.2f}°{hemisphere_lat}, {abs(lon):.2f}°{hemisphere_lon}")
calculate_distance_info(locations)
# 2D/3D points
points_2d = [(0, 0), (1, 1), (2, 4), (3, 9)]
points_3d = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
print(f"\n2D Points: {points_2d}")
print(f"3D Points: {points_3d}")Configuration and Settings
# Application configuration
config = (
('DEBUG', True),
('MAX_CONNECTIONS', 100),
('TIMEOUT', 30),
('DATABASE_URL', 'postgresql://localhost/mydb')
)
# Process configuration
settings = {}
for key, value in config:
settings[key] = value
print(f"{key}: {value}")
# RGB color definitions
colors = {
'red': (255, 0, 0),
'green': (0, 255, 0),
'blue': (0, 0, 255),
'white': (255, 255, 255),
'black': (0, 0, 0)
}
def get_color_info(color_name):
"""Get RGB values for a color."""
if color_name in colors:
r, g, b = colors[color_name]
return f"{color_name.title()}: RGB({r}, {g}, {b})"
return f"Color '{color_name}' not found"
print(f"\n{get_color_info('red')}")
print(f"{get_color_info('blue')}")Tuples vs Lists vs Sets
Understanding when to use each data structure.
Comparison
# Same data in different structures
data_tuple = (1, 2, 3, 2, 4)
data_list = [1, 2, 3, 2, 4]
data_set = {1, 2, 3, 4} # Note: duplicates removed
print("Data Structures Comparison:")
print(f"Tuple: {data_tuple}")
print(f"List: {data_list}")
print(f"Set: {data_set}")
# Memory usage (tuples are more memory efficient)
import sys
print(f"\nMemory usage:")
print(f"Tuple: {sys.getsizeof(data_tuple)} bytes")
print(f"List: {sys.getsizeof(data_list)} bytes")
# Performance (tuples are faster for access)
import timeit
tuple_access = timeit.timeit(lambda: data_tuple[2], number=1000000)
list_access = timeit.timeit(lambda: data_list[2], number=1000000)
print(f"\nAccess performance (1M operations):")
print(f"Tuple: {tuple_access:.4f} seconds")
print(f"List: {list_access:.4f} seconds")When to Use Each
# Use tuples for:
# 1. Fixed collections that won't change
coordinates = (latitude, longitude)
rgb_color = (255, 128, 0)
database_record = (id, name, email, created_date)
# 2. Dictionary keys (tuples are hashable)
locations = {
(0, 0): "Origin",
(1, 1): "Point A",
(2, 2): "Point B"
}
# 3. Function returns with multiple values
def get_name_age():
return "John", 25 # Returns a tuple
name, age = get_name_age() # Tuple unpacking
# Use lists for:
# 1. Collections that need modification
shopping_cart = ['milk', 'eggs', 'bread']
shopping_cart.append('cheese') # Can modify
# 2. Unknown final size
user_inputs = []
# Add items dynamically
# Use sets for:
# 1. Unique collections
unique_visitors = {'user1', 'user2', 'user3'}
# 2. Mathematical operations
tags_a = {'python', 'data', 'analysis'}
tags_b = {'python', 'machine', 'learning'}
common_tags = tags_a & tags_b # IntersectionAdvanced Tuple Techniques
More sophisticated tuple usage patterns.
Named Tuples
from collections import namedtuple
# Create a named tuple class
Point = namedtuple('Point', ['x', 'y'])
Person = namedtuple('Person', ['name', 'age', 'city'])
# Create instances
origin = Point(0, 0)
point_a = Point(3, 4)
john = Person('John Doe', 30, 'New York')
jane = Person('Jane Smith', 25, 'Boston')
# Access by name or index
print(f"Origin: {origin}")
print(f"Point A: x={point_a.x}, y={point_a.y}")
print(f"John: {john.name}, {john.age} years old")
# Still works like regular tuple
print(f"John by index: {john[0]}, {john[1]}")
# Useful methods
print(f"Point fields: {point_a._fields}")
print(f"John as dict: {john._asdict()}")
# Create new instance with some fields changed
older_john = john._replace(age=31)
print(f"Older John: {older_john}")Tuple Comprehensions and Generator Expressions
# Generator expression (not tuple comprehension)
squared_gen = (x**2 for x in range(5))
print(f"Generator: {squared_gen}")
# Convert to tuple
squared_tuple = tuple(x**2 for x in range(5))
print(f"Squared tuple: {squared_tuple}")
# Practical example: Process data into tuples
sales_data = [
{'product': 'A', 'price': 100, 'quantity': 5},
{'product': 'B', 'price': 200, 'quantity': 3},
{'product': 'C', 'price': 150, 'quantity': 4}
]
# Create tuples of (product, total_value)
sales_tuples = tuple(
(item['product'], item['price'] * item['quantity'])
for item in sales_data
)
print(f"Sales totals: {sales_tuples}")
for product, total in sales_tuples:
print(f"{product}: ${total}")Practice Exercise
Work with tuples in a data analysis context:
def analyze_student_grades():
"""Analyze student grade data using tuples."""
# Student data: (name, course, grade, credits)
students = [
('Alice Johnson', 'Mathematics', 92, 3),
('Alice Johnson', 'Physics', 88, 4),
('Alice Johnson', 'Chemistry', 95, 3),
('Bob Smith', 'Mathematics', 78, 3),
('Bob Smith', 'Physics', 82, 4),
('Bob Smith', 'English', 90, 3),
('Carol Davis', 'Mathematics', 96, 3),
('Carol Davis', 'Physics', 91, 4),
('Carol Davis', 'Biology', 94, 4)
]
print("Student Grade Analysis")
print("=" * 50)
# Calculate GPA for each student
student_gpas = {}
for name, course, grade, credits in students:
if name not in student_gpas:
student_gpas[name] = []
# Convert grade to GPA points
if grade >= 90:
gpa_points = 4.0
elif grade >= 80:
gpa_points = 3.0
elif grade >= 70:
gpa_points = 2.0
else:
gpa_points = 1.0
student_gpas[name].append((gpa_points, credits))
# Calculate weighted GPA
print("Student GPAs:")
for name, grade_data in student_gpas.items():
total_points = sum(gpa * credits for gpa, credits in grade_data)
total_credits = sum(credits for gpa, credits in grade_data)
weighted_gpa = total_points / total_credits
print(f"{name}: {weighted_gpa:.2f} GPA")
# Course statistics
course_stats = {}
for name, course, grade, credits in students:
if course not in course_stats:
course_stats[course] = []
course_stats[course].append(grade)
print(f"\nCourse Statistics:")
for course, grades in course_stats.items():
avg_grade = sum(grades) / len(grades)
min_grade = min(grades)
max_grade = max(grades)
print(f"{course}:")
print(f" Average: {avg_grade:.1f}")
print(f" Range: {min_grade} - {max_grade}")
# Run the analysis
analyze_student_grades()Summary
Tuples provide immutable, ordered collections perfect for fixed data sets. Key features include tuple packing/unpacking, use as dictionary keys, and memory efficiency. They excel in scenarios requiring data integrity, like coordinates, database records, and configuration settings.
© 2025 Prof. Tim Frenzel. All rights reserved. | Version 1.0.5