How to use 'min' and 'max' in Python

Learn how to use Python's min() and max() functions. This guide covers different methods, tips, real-world applications, and debugging errors.

How to use 'min' and 'max' in Python
Published on: 
Tue
Mar 3, 2026
Updated on: 
Wed
Apr 1, 2026
The Replit Team

Python's min() and max() functions are essential tools to identify the smallest and largest values in any iterable. They work on simple lists and complex data structures alike.

In this article, you'll explore advanced techniques and practical tips for both functions. You'll find real-world applications and learn how to debug common pitfalls, so you can use min() and max() with confidence.

Basic usage of min() and max()

numbers = [42, 17, 8, 94, 31, 5]
minimum = min(numbers)
maximum = max(numbers)
print(f"Minimum: {minimum}, Maximum: {maximum}")--OUTPUT--Minimum: 5, Maximum: 94

The code passes the list numbers directly to the min() and max() functions. This is their most fundamental use case—they scan an iterable and return the single lowest or highest value without requiring any extra logic.

This approach is highly efficient because it avoids the overhead of sorting the entire list first. When you only need an extreme value, using min() or max() is a much faster operation than performing a full sort.

Working with different data types

The power of min() and max() isn't limited to lists of numbers; they also work seamlessly with other data types like tuples, sets, strings, and even dictionaries.

Using min() and max() with tuples and sets

my_tuple = (15, 3, 27, 8)
my_set = {42, 17, 8, 94}
print(f"Tuple min: {min(my_tuple)}, max: {max(my_tuple)}")
print(f"Set min: {min(my_set)}, max: {max(my_set)}")--OUTPUT--Tuple min: 3, max: 27
Set min: 8, max: 94

Just as with lists, you can pass a tuple or set directly to the min() and max() functions. They work by iterating through the collection's elements to find the extreme values. Here’s how it works for each:

  • With a tuple like my_tuple, the functions simply scan the elements from start to finish.
  • For a set like my_set, which is an unordered collection, min() and max() still efficiently find the smallest and largest items.

Using min() and max() with strings

words = ["apple", "banana", "cherry", "date"]
print(f"Alphabetically first: {min(words)}")
print(f"Alphabetically last: {max(words)}")
print(f"Shortest word: {min(words, key=len)}")
print(f"Longest word: {max(words, key=len)}")--OUTPUT--Alphabetically first: apple
Alphabetically last: date
Shortest word: date
Longest word: banana

When you use min() and max() on a list of strings, they perform an alphabetical comparison by default. This is why min(words) returns "apple" and max(words) returns "date".

Things get more interesting with the key argument. By passing key=len, you're telling the functions to compare the items based on their length, not their alphabetical value. This allows you to:

  • Find the shortest string using min(words, key=len), which returns "date".
  • Find the longest string using max(words, key=len), which returns "banana".

Working with dictionaries using min() and max()

scores = {"Alice": 92, "Bob": 85, "Charlie": 97, "Dave": 78}
lowest_scorer = min(scores, key=scores.get)
highest_scorer = max(scores, key=scores.get)
print(f"Lowest score: {lowest_scorer} with {scores[lowest_scorer]}")
print(f"Highest score: {highest_scorer} with {scores[highest_scorer]}")--OUTPUT--Lowest score: Dave with 78
Highest score: Charlie with 97

When you use min() and max() on a dictionary, they iterate over the keys by default. To find the key associated with an extreme value, you need the key argument. By setting key=scores.get, you're telling the functions to use the dictionary's values for comparison instead of its keys.

  • min(scores, key=scores.get) finds the key with the lowest score, returning "Dave".
  • max(scores, key=scores.get) finds the key with the highest score, returning "Charlie".

This technique is a common pattern for finding an item in a dictionary based on its value.

Advanced techniques and use cases

Building on the key argument, you can extend min() and max() to handle custom objects, find multiple extreme values, and manage empty sequences gracefully.

Using min() and max() with custom objects

class Product:
def __init__(self, name, price):
self.name = name
self.price = price

def __repr__(self):
return f"{self.name}: ${self.price}"

products = [Product("Laptop", 1200), Product("Phone", 800), Product("Tablet", 500)]
cheapest = min(products, key=lambda p: p.price)
most_expensive = max(products, key=lambda p: p.price)
print(f"Cheapest: {cheapest}\nMost expensive: {most_expensive}")--OUTPUT--Cheapest: Tablet: $500
Most expensive: Laptop: $1200

When working with custom objects like the Product class, Python doesn't inherently know how to compare them. You need to provide a clear instruction using the key argument. In this case, a lambda function tells min() and max() which attribute to use for comparison.

  • The expression key=lambda p: p.price instructs the functions to look only at the price of each Product object.
  • As a result, min() returns the entire Product object with the lowest price, not just the price value itself.

Finding multiple minimums and maximums with heapq

import heapq
numbers = [42, 17, 8, 94, 31, 5, 11, 63]
three_smallest = heapq.nsmallest(3, numbers)
three_largest = heapq.nlargest(3, numbers)
print(f"Three smallest: {three_smallest}")
print(f"Three largest: {three_largest}")--OUTPUT--Three smallest: [5, 8, 11]
Three largest: [94, 63, 42]

When you need more than just one extreme value, Python's heapq module is the right tool. It's designed for this exact purpose and is more efficient than sorting the entire list first, especially with large datasets. The module provides two key functions:

  • heapq.nsmallest(n, iterable) finds the n smallest items.
  • heapq.nlargest(n, iterable) finds the n largest items.

In the example, they quickly return the three smallest and three largest numbers from the list without extra work on your part.

Using min() and max() with default arguments

empty_list = []
# This would raise ValueError: min() arg is an empty sequence
# min(empty_list)
# Using default value instead:
min_value = min(empty_list, default=0)
max_value = max(empty_list, default=0)
print(f"Min with default: {min_value}")
print(f"Max with default: {max_value}")--OUTPUT--Min with default: 0
Max with default: 0

Calling min() or max() on an empty sequence normally raises a ValueError because there are no items to compare. This can crash your program if it isn't handled. That’s where the default argument comes in handy.

  • It provides a fallback value that the function returns if the iterable is empty.
  • Using min(empty_list, default=0) returns 0 instead of an error, giving you a clean way to manage empty sequences without extra checks.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed. You can skip the setup and start coding instantly, moving directly from learning techniques like min() and max() to applying them.

Instead of just piecing together functions, you can build complete apps. Describe what you want to build, and Agent 4 takes your idea to a working product. It can write the code, connect databases, and handle deployment based on your description.

  • A price comparison tool that finds the cheapest and most expensive items from a list of products.
  • A social media dashboard that identifies the post with the highest engagement from your account data.
  • A leaderboard utility that displays the top three scores for a game.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

While min() and max() are powerful, you can run into a few common issues that are easy to solve once you know what to look for.

  • Handling TypeError when comparing mixed types: A TypeError occurs when you try to compare incompatible data types, like an integer and a string. Python can't determine an order, so it raises an error. To fix this, ensure all elements are comparable or use the key argument to extract a consistent value from each item.
  • Case sensitivity when using min() and max() with strings: By default, these functions are case-sensitive, treating uppercase letters as "smaller" than lowercase ones. This means "Z" comes before "a". For a true alphabetical comparison, use key=str.lower to ignore case during the operation.
  • Handling NaN values with min() and max(): In data analysis, you might find NaN (Not a Number) values. Because NaN isn't comparable to any number, its presence will cause both min() and max() to return NaN. The best approach is to filter these values out of your iterable before finding the minimum or maximum.

Handling TypeError when comparing mixed types

Python's min() and max() functions need a consistent way to compare elements. When you mix incompatible types, like integers and strings, Python can't decide which is "smaller" or "larger" and raises a TypeError. The code below shows this exact scenario.

mixed_list = [42, "hello", 10, "world"]
minimum = min(mixed_list) # This will raise TypeError
print(f"Minimum value: {minimum}")

The function attempts to find the smallest value by comparing each element sequentially. The process stops and raises an error when it tries to determine if 42 is smaller or larger than "hello". See how to fix this below.

# Separate by type first
numbers = [x for x in mixed_list if isinstance(x, int)]
strings = [x for x in mixed_list if isinstance(x, str)]
print(f"Minimum number: {min(numbers)}")
print(f"Minimum string: {min(strings)}")

The fix is to filter the list into separate, type-specific collections before comparison. The example uses list comprehensions with isinstance(x, int) and isinstance(x, str) to create new lists containing only numbers or strings. This ensures min() only compares compatible types, avoiding the TypeError. This error often appears when you're working with data from files or APIs, where you can't always guarantee consistent data types.

Case sensitivity when using min() and max() with strings

When working with strings, min() and max() are case-sensitive by default, which can produce counterintuitive alphabetical results. Uppercase letters are treated as 'smaller' than their lowercase counterparts, disrupting a natural sort order. The code below demonstrates this exact problem.

words = ["Apple", "banana", "Cherry", "date"]
print(f"Alphabetically first: {min(words)}")
print(f"Alphabetically last: {max(words)}")

The functions return "Apple" as the minimum because its capital 'A' precedes the lowercase 'b' in "banana". This sorting is based on character codes, not a purely alphabetical order. See how to fix this below.

words = ["Apple", "banana", "Cherry", "date"]
print(f"Alphabetically first: {min(words, key=str.lower)}")
print(f"Alphabetically last: {max(words, key=str.lower)}")

The fix is to use the key argument with str.lower. This tells min() and max() to compare the strings based on their lowercase versions, not their original forms. As a result, "Apple" is treated the same as "apple," ensuring a true alphabetical sort.

This is crucial when you're working with user-generated text or any data where capitalization isn't consistent, as it prevents unexpected sorting behavior caused by character codes.

Handling NaN values with min() and max()

In data analysis, NaN (Not a Number) values represent missing information. They're problematic for min() and max() because NaN isn't comparable to any number, causing both functions to return NaN. The code below shows this in action.

import numpy as np
data = [42, 17, 8, np.nan, 31]
minimum = min(data) # NaN comparison will make this fail
maximum = max(data)
print(f"Minimum: {minimum}, Maximum: {maximum}")

The functions try to compare each element, but any comparison involving np.nan is false. This prevents them from finding a true extreme value, so they return NaN. See how to get the correct result below.

import numpy as np
data = [42, 17, 8, np.nan, 31]
clean_data = [x for x in data if not np.isnan(x)]
minimum = min(clean_data)
maximum = max(clean_data)
print(f"Minimum: {minimum}, Maximum: {maximum}")

The fix is to filter out NaN values before calling min() or max(). The example does this efficiently with a list comprehension and the np.isnan(x) function, creating a new list that contains only valid numbers. This allows the functions to work correctly. You'll often encounter this problem when dealing with data from scientific computing or external datasets where missing values are represented as NaN.

Real-world applications

With a solid grasp of how to avoid pitfalls, you can apply min() and max() to practical tasks like financial analysis and finding outliers.

Using min() and max() for financial analysis

In finance, you can use min() and max() to quickly calculate key metrics like price range and volatility from a series of stock prices.

stock_prices = [156.78, 152.45, 163.22, 157.90, 159.75, 161.20]
price_range = max(stock_prices) - min(stock_prices)
percent_volatility = (price_range / min(stock_prices)) * 100
print(f"Price range: ${price_range:.2f}")
print(f"Volatility: {percent_volatility:.2f}%")

This snippet shows how min() and max() can be used for simple financial analysis on the stock_prices list. The code performs two key calculations:

  • It determines the price_range by subtracting the lowest price, found with min(), from the highest price, found with max().
  • It then calculates percent_volatility to measure the price swing relative to its lowest point.

This gives you a quick snapshot of the stock's movement without needing complex libraries.

Finding outliers in datasets with min() and max()

You can use min() and max() to spot the most extreme values in a dataset, which are often the first clue to identifying potential outliers.

import numpy as np

measurements = [102, 104, 98, 101, 99, 97, 143, 100, 103, 95]
q1, q3 = np.percentile(measurements, [25, 75])
iqr = q3 - q1
lower_bound = q1 - 1.5 * iqr
upper_bound = q3 + 1.5 * iqr

outliers = [x for x in measurements if x < lower_bound or x > upper_bound]
print(f"Identified outliers: {outliers}")

This snippet uses the NumPy library to programmatically identify outliers in the measurements list. It’s a more robust approach than just picking the absolute min() or max().

  • First, it uses np.percentile to find the values that mark the boundaries of the central 50% of the data.
  • It then calculates a lower_bound and an upper_bound to define a "normal" range based on the spread of that central data.

A list comprehension then filters the original list, collecting any number that falls outside these bounds, which effectively isolates values like 143.

Get started with Replit

Turn your knowledge of min() and max() into a real tool. Describe what you want to build to Replit Agent, like "a tool to find the price range in a stock dataset" or "a script that identifies outlier sensor readings".

Replit Agent writes the code, tests for errors, and deploys your app from a simple description. Start building with Replit.

Build your first app today

Describe what you want to build, and Replit Agent writes the code, handles the infrastructure, and ships it live. Go from idea to real product, all in your browser.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.