ZetCode

Python __lt__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __lt__ 方法,这是一个实现小于比较操作的特殊方法。我们将介绍基本用法、排序、丰富的比较方法和实际示例。

基本定义

__lt__ 方法是 Python 的丰富比较方法之一。 它代表“小于”,并在使用 < 运算符时调用。该方法应返回 TrueFalse

主要特点:它接受两个参数(selfother),应该实现有意义的比较逻辑,并被排序函数使用。它为对象启用自定义比较行为。

基本 __lt__ 实现

这是一个简单的实现,展示了 __lt__ 如何与自定义类一起工作。我们将根据属性值比较对象。

basic_lt.py
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
    
    def __lt__(self, other):
        return self.price < other.price

p1 = Product("Laptop", 999)
p2 = Product("Phone", 699)

print(p1 < p2)  # False
print(p2 < p1)  # True

此示例根据其 price 属性比较 Product 实例。如果当前实例的 price 小于另一个实例的 price,则 __lt__ 方法返回 True。

当我们使用 < 运算符时,Python 会自动使用要比较的两个对象调用 __lt__ 方法。

使用 __lt__ 排序对象

__lt__ 方法支持对象的自定义排序。 Python 的内置 sorted() 函数使用此方法进行比较。

sorting.py
class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade
    
    def __lt__(self, other):
        return self.grade < other.grade
    
    def __repr__(self):
        return f"{self.name}: {self.grade}"

students = [
    Student("Alice", 85),
    Student("Bob", 72),
    Student("Charlie", 90)
]

sorted_students = sorted(students)
print(sorted_students)

此示例按年级对 Student 对象进行排序。 __lt__ 方法定义了比较逻辑,sorted() 使用它按从低到高的年级对学生进行排序。

__repr__ 方法为打印排序后的列表提供了一个可读的字符串表示形式。

比较不同类型

当比较不可能时,__lt__ 可以通过返回 NotImplemented 来处理不同类型之间的比较。

different_types.py
class Temperature:
    def __init__(self, value, unit='C'):
        self.value = value
        self.unit = unit
    
    def __lt__(self, other):
        if isinstance(other, Temperature):
            if self.unit == other.unit:
                return self.value < other.value
            elif self.unit == 'C' and other.unit == 'F':
                return self.value < (other.value - 32) * 5/9
            else:
                return (self.value * 9/5 + 32) < other.value
        return NotImplemented

t1 = Temperature(25)  # 25°C
t2 = Temperature(77, 'F')  # 77°F

print(t1 < t2)  # False (25°C is 77°F)
print(t2 < t1)  # False
print(t1 < 30)  # TypeError

即使单位不同(摄氏度与华氏度),此 Temperature 类也会比较值。对于不兼容的类型,它返回 NotImplemented,这使得 Python 引发 TypeError

该方法首先检查另一个对象是否是 Temperature,然后在比较之前处理单位转换。

使用 functools 进行完全排序

在实现 __lt__ 时,可以使用 functools.total_ordering 自动提供其他比较方法。

total_ordering.py
from functools import total_ordering

@total_ordering
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.area = width * height
    
    def __lt__(self, other):
        return self.area < other.area
    
    def __eq__(self, other):
        return self.area == other.area

r1 = Rectangle(3, 4)
r2 = Rectangle(2, 6)
r3 = Rectangle(4, 4)

print(r1 < r2)   # False (12 < 12)
print(r1 <= r2)  # True  (12 <= 12)
print(r1 > r3)   # False (12 > 16)

total_ordering 装饰器从 __lt____eq__ 生成所有比较方法(__le____gt__ 等)。 这减少了样板代码。

在这里,矩形按面积进行比较。我们仅实现 __lt____eq__,但获得了所有比较操作。

反向排序

您可以通过反转 __lt__ 中的比较逻辑或在排序中使用 reverse 参数来实现反向排序。

reverse_order.py
class Employee:
    def __init__(self, name, years_of_service):
        self.name = name
        self.years = years_of_service
    
    def __lt__(self, other):
        # Higher years comes first (reverse order)
        return self.years > other.years
    
    def __repr__(self):
        return f"{self.name} ({self.years} years)"

employees = [
    Employee("Alice", 3),
    Employee("Bob", 10),
    Employee("Charlie", 5)
]

# Sorted uses __lt__, which we defined for reverse order
sorted_employees = sorted(employees)
print(sorted_employees)

# Alternative: keep normal __lt__ and use reverse=True

此示例显示了反向排序的两种方法。第一个反转了 __lt__ 中的比较,而第二个保持正常比较并在 sorted() 中使用了 reverse=True

当您总是希望对对象进行反向排序时,第一种方法很有用,而第二种方法提供了更大的灵活性。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程