杰瑞科技汇

Python中sorted函数的cmp参数如何使用?

Of course! This is a classic and important topic in Python, as it highlights a key difference between Python 2 and Python 3.

Python中sorted函数的cmp参数如何使用?-图1
(图片来源网络,侵删)

Let's break it down.

The Short Answer (Python 3)

In Python 3, the cmp argument has been removed from the built-in sorted() function and the .sort() method.

Instead, you should use the key argument or, for complex custom logic, the functools.cmp_to_key utility.


The Detailed Explanation

The cmp Function in Python 2 (The Old Way)

In Python 2, sorted() and .sort() accepted a cmp argument. This was a function that took two arguments and returned:

Python中sorted函数的cmp参数如何使用?-图2
(图片来源网络,侵删)
  • A negative number if the first argument was "less than" the second.
  • Zero if they were "equal".
  • A positive number if the first argument was "greater than" the second.

Example in Python 2 Style:

Let's say we want to sort a list of tuples by their sum.

# This is how you would have done it in Python 2
data = [(1, 5), (2, 3), (3, 1)]
def compare_tuples(a, b):
    """Compare two tuples based on their sum."""
    sum_a = sum(a)
    sum_b = sum(b)
    if sum_a < sum_b:
        return -1
    elif sum_a > sum_b:
        return 1
    else:
        return 0
# Using the cmp argument
sorted_data = sorted(data, cmp=compare_tuples)
print(sorted_data)
# Output: [(3, 1), (2, 3), (1, 5)]

This works, but it's less efficient and considered less "Pythonic" than the modern key approach.


The Modern key Argument (The Python 3 Way)

The key argument is the preferred, more powerful, and more efficient way to customize sorting in Python 3.

Python中sorted函数的cmp参数如何使用?-图3
(图片来源网络,侵删)

Instead of a comparison function, key takes a function that is called on every element of the list before making comparisons. The sorting is then performed on the returned key values, not the original elements.

Key Advantages of key:

  • More Efficient: The key function is called only once per element, whereas the cmp function is called multiple times for each comparison. This leads to better performance, especially with large lists.
  • More Readable: The intent is clearer. You're defining "what to sort by" (the key), not "how to compare two items".
  • More Flexible: You can easily sort by multiple criteria or complex properties.

Example using key:

Let's achieve the same result as the Python 2 example, but the modern way.

data = [(1, 5), (2, 3), (3, 1)]
# The key function is applied to each element before sorting.
# We want to sort by the sum of the tuple.
def get_tuple_sum(t):
    return sum(t)
sorted_data = sorted(data, key=get_tuple_sum)
print(sorted_data)
# Output: [(3, 1), (2, 3), (1, 5)]

This is cleaner and more direct. You can even use a lambda function for simple cases:

data = [(1, 5), (2, 3), (3, 1)]
# Sort by the sum of each tuple using a lambda
sorted_data = sorted(data, key=lambda t: sum(t))
print(sorted_data)
# Output: [(3, 1), (2, 3), (1, 5)]

When to Use functools.cmp_to_key (The Bridge)

Sometimes, your logic is genuinely based on a comparison between two elements. For example, you might be implementing a custom comparison algorithm that is difficult to express as a simple key. In these rare cases, you can use functools.cmp_to_key.

This handy utility converts an old-style cmp function into a key function that sorted() can understand.

Example:

Let's say we want to sort strings based on their length, but with a twist: if two strings have the same length, we want to sort them in reverse alphabetical order. This logic is easier to express as a comparison between two items (a and b).

import functools
data = ['apple', 'pie', 'banana', 'pear']
def custom_compare(a, b):
    """
    Compares two strings.
    Returns:
        -1 if a should come before b
        1 if a should come after b
        0 if they are equal
    """
    len_a = len(a)
    len_b = len(b)
    # Primary sort: by length (ascending)
    if len_a < len_b:
        return -1
    elif len_a > len_b:
        return 1
    # Secondary sort: if lengths are equal, sort alphabetically in reverse
    # (i.e., 'pie' comes before 'pear')
    if a > b:
        return -1
    elif a < b:
        return 1
    return 0
# Convert the cmp function to a key function and use it
sorted_data = sorted(data, key=functools.cmp_to_key(custom_compare))
print(sorted_data)
# Expected Output: ['pie', 'pear', 'apple', 'banana']
# Explanation:
# 1. 'pie' and 'pear' (length 3) come before 'apple' and 'banana' (length 5, 6).
# 2. Between 'pie' and 'pear', 'pie' > 'pear', so our custom_compare returns -1,
#    placing 'pie' first.

Summary Table

Feature cmp (Python 2) key (Python 3) functools.cmp_to_key (Python 3)
What it takes A function that takes two arguments (a, b) A function that takes one argument (an element) A cmp function (same as Python 2)
What it returns -1, 0, or 1 A value to be used for sorting (e.g., an integer, string) A key function
When to use Never in Python 3. (Only for legacy Python 2 code). Almost always. For 99% of custom sorting needs. When your sorting logic is inherently a two-item comparison and hard to express as a single key.
Performance Less efficient (called many times) More efficient (called once per element) Same as using a key, but the underlying cmp logic is still less efficient than a direct key.
分享:
扫描分享到社交APP
上一篇
下一篇