Welcome to DRIXO — Your Coding Journey Starts Here
DRIXO Code • Learn • Build

Python Lists vs Tuples vs Sets: When to Use What

January 03, 2026 8 min read 0 Comments
Python Lists vs Tuples vs Sets: When to Use What
Python

Python Lists vs Tuples vs Sets: When to Use What

DRIXO

Code · Learn · Build

When I first learned about python lists vs tuples vs sets, I made every mistake possible. This tutorial is the guide I wish I had — clear, practical, and filled with real code.

Understanding Data Structures

Let's start with the fundamentals of data structures in Python. These concepts form the building blocks for everything else.

# Data Structures — Core Concepts

# Example 1: Basic demonstration
def demonstrate():
    """Shows the core concept of Data Structures"""
    data = [10, 20, 30, 40, 50]

    # Process data
    result = [x * 2 for x in data if x > 20]
    print(f"Filtered and doubled: {result}")

    # Using dictionary comprehension
    indexed = {f"item_{i}": val for i, val in enumerate(data)}
    print(f"Indexed: {indexed}")

    return result

output = demonstrate()
print(f"Final output: {output}")

Practical Implementation

# Data Structures — Practical patterns you'll use every day

class DataProcessor:
    """A reusable data processing class demonstrating Data Structures"""

    def __init__(self, data):
        self._data = list(data)
        self._operations = []

    def filter_by(self, condition):
        """Filter items based on a condition function"""
        self._data = [item for item in self._data if condition(item)]
        self._operations.append('filter')
        return self

    def transform(self, func):
        """Apply transformation to each item"""
        self._data = [func(item) for item in self._data]
        self._operations.append('transform')
        return self

    def sort_by(self, key=None, reverse=False):
        """Sort the data"""
        self._data.sort(key=key, reverse=reverse)
        self._operations.append('sort')
        return self

    @property
    def result(self):
        return list(self._data)

    def __repr__(self):
        return f"DataProcessor({len(self._data)} items, ops={self._operations})"


# Usage example
numbers = [15, 3, 42, 7, 28, 91, 56, 12]
result = (DataProcessor(numbers)
    .filter_by(lambda x: x > 10)
    .transform(lambda x: x ** 2)
    .sort_by(reverse=True)
    .result)

print(f"Result: {result}")
# Result: [8281, 3136, 1764, 784, 225, 144]

Error Handling and Edge Cases

# Robust Data Structures with proper error handling

def safe_process(data, operation, default=None):
    """
    Safely process data with error handling.

    Args:
        data: Input data to process
        operation: Function to apply
        default: Fallback value on error

    Returns:
        Processed data or default value
    """
    if data is None:
        return default

    try:
        result = operation(data)
        return result
    except (TypeError, ValueError) as e:
        print(f"Processing error: {e}")
        return default
    except Exception as e:
        print(f"Unexpected error: {type(e).__name__}: {e}")
        raise  # Re-raise unexpected errors

# Example usage
print(safe_process([1, 2, 3], sum))         # 6
print(safe_process(None, sum, default=0))    # 0
print(safe_process("123", int))              # 123
print(safe_process("abc", int, default=-1))  # -1

# Context manager for resource cleanup
from contextlib import contextmanager

@contextmanager
def managed_resource(name):
    print(f"Opening {name}...")
    resource = {'name': name, 'data': []}
    try:
        yield resource
    except Exception as e:
        print(f"Error with {name}: {e}")
        raise
    finally:
        print(f"Closing {name}")

with managed_resource("database") as db:
    db['data'].append("record_1")
    print(f"Working with {db['name']}: {db['data']}")

Testing Your Code

# Testing Data Structures with pytest-style tests

def test_data_processor():
    """Test the DataProcessor class"""
    # Test filtering
    dp = DataProcessor([1, 2, 3, 4, 5])
    result = dp.filter_by(lambda x: x > 3).result
    assert result == [4, 5], f"Expected [4, 5], got {result}"

    # Test transformation
    dp = DataProcessor([1, 2, 3])
    result = dp.transform(lambda x: x * 10).result
    assert result == [10, 20, 30], f"Expected [10, 20, 30], got {result}"

    # Test chaining
    dp = DataProcessor([5, 3, 8, 1, 9, 2])
    result = dp.filter_by(lambda x: x > 3).sort_by().result
    assert result == [5, 8, 9], f"Expected [5, 8, 9], got {result}"

    # Test empty input
    dp = DataProcessor([])
    result = dp.filter_by(lambda x: x > 0).result
    assert result == [], f"Expected [], got {result}"

    print("All tests passed!")

test_data_processor()
Pro Tip: Write tests for edge cases first: empty inputs, None values, single elements, and very large datasets. These catch most bugs.

Summary and Best Practices

Here are the key takeaways for working with data structures in Python:

  • Keep it simple — Python's philosophy is readability. Choose clarity over cleverness.
  • Use type hints — They serve as documentation and catch bugs early.
  • Handle errors gracefully — Use try/except with specific exception types.
  • Write tests — Even simple assert statements catch regressions.
  • Profile before optimizing — Don't guess where bottlenecks are.
# Clean, production-ready template
from typing import List, Optional, Callable, TypeVar

T = TypeVar('T')

def process_items(
    items: List[T],
    filter_fn: Optional[Callable[[T], bool]] = None,
    transform_fn: Optional[Callable[[T], T]] = None,
) -> List[T]:
    """Process a list of items with optional filtering and transformation."""
    result = items
    if filter_fn:
        result = [item for item in result if filter_fn(item)]
    if transform_fn:
        result = [transform_fn(item) for item in result]
    return result
AM
Arjun Mehta
Full-Stack Developer & Technical Writer at DRIXO

Full-stack developer with 5+ years of experience in Python and JavaScript. I love breaking down complex concepts into simple, practical tutorials. When I'm not coding, you'll find me contributing to open-source projects.

Comments