ZetCode

Python __floordiv__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __floordiv__ 方法,这是一个实现地板除法(// 运算符)的特殊方法。我们将介绍基本用法、运算符重载、自定义数值类型和实际示例。

基本定义

__floordiv__ 方法是一个特殊方法,它在 Python 中实现地板除法运算 (//)。 当在两个对象之间使用 // 运算符时,会调用它。

主要特征:它必须返回地板除法结果,可以为任何类定义,并且如果需要,应该处理类型转换。 相应的反射操作是 __rfloordiv__

基本的 __floordiv__ 实现

这是一个简单的实现,展示了 __floordiv__ 如何与自定义类一起工作。 这演示了基本的运算符重载模式。

basic_floordiv.py
class Number:
    def __init__(self, value):
        self.value = value
    
    def __floordiv__(self, other):
        if isinstance(other, Number):
            return Number(self.value // other.value)
        elif isinstance(other, (int, float)):
            return Number(self.value // other)
        else:
            return NotImplemented

a = Number(10)
b = Number(3)
result = a // b
print(result.value)  # Output: 3

此示例显示了一个实现地板除法的基本 Number 类。 该方法处理除以另一个 Number 或一个常规数字,并返回一个包含结果的新 Number 实例。

NotImplemented 返回值告诉 Python,如果给定类型不支持该操作,则尝试其他方法,例如 __rfloordiv__

处理不同的数值类型

一个健壮的 __floordiv__ 实现应该处理各种数值类型,并为不支持的操作提供有意义的错误消息。

numeric_types.py
class Distance:
    def __init__(self, meters):
        self.meters = meters
    
    def __floordiv__(self, other):
        if isinstance(other, Distance):
            return self.meters // other.meters
        elif isinstance(other, (int, float)):
            return Distance(self.meters // other)
        else:
            raise TypeError(f"Unsupported type for //: {type(other)}")

d1 = Distance(100)
d2 = Distance(30)
print(d1 // d2)  # Output: 3
print(d1 // 4)   # Creates new Distance(25)

这个 Distance 类处理与其他 Distance 对象(返回一个标量)和数字(返回一个新的 Distance)的地板除法。 对于不支持的类型,它会引发 TypeError。

该实现展示了如何根据右手操作数返回不同的类型,这在数值运算中是一种常见的模式。

实现 __rfloordiv__

当左操作数不支持该操作时,__rfloordiv__ 方法会处理这种情况,从而启用诸如 5 // obj 之类的操作。

reflected_floordiv.py
class Fraction:
    def __init__(self, numerator, denominator):
        self.n = numerator
        self.d = denominator
    
    def __floordiv__(self, other):
        if isinstance(other, Fraction):
            return (self.n * other.d) // (self.d * other.n)
        elif isinstance(other, (int, float)):
            return (self.n // (self.d * other))
        else:
            return NotImplemented
    
    def __rfloordiv__(self, other):
        if isinstance(other, (int, float)):
            return (other * self.d) // self.n
        else:
            return NotImplemented

half = Fraction(1, 2)
print(10 // half)  # Output: 20 (uses __rfloordiv__)
print(half // 0.1) # Output: 5 (uses __floordiv__)

这个 Fraction 类实现了常规的和反射的地板除法。 __rfloordiv__ 方法启用了 Fraction 位于 // 运算符右侧的操作。

该示例演示了如何正确实现这两种方法,以支持具有不同操作数顺序的类交换操作。

自定义地板除法行为

__floordiv__ 可以实现特定于域的地板除法行为,该行为与标准数值除法不同。

custom_behavior.py
class TimeSlot:
    def __init__(self, minutes):
        self.minutes = minutes
    
    def __floordiv__(self, other):
        if isinstance(other, TimeSlot):
            return self.minutes // other.minutes
        elif isinstance(other, (int, float)):
            # Return list of equal time slots
            slot_size = self.minutes // other
            return [TimeSlot(slot_size) for _ in range(other)]
        else:
            return NotImplemented

meeting = TimeSlot(90)
print(meeting // 3)  # Output: [TimeSlot(30), TimeSlot(30), TimeSlot(30)]

这个 TimeSlot 类实现了自定义地板除法行为。 当除以一个数字时,它返回一个相等时间段的列表,而不是一个单一值。

这演示了如何将 __floordiv__ 用于超出简单算术的特定于域的操作,并在适当时返回复杂的结果。

带负数的的地板除法

带负数的的地板除法具有特定的行为,在实现 __floordiv__ 时应考虑该行为。

negative_numbers.py
class SignedNumber:
    def __init__(self, value):
        self.value = value
    
    def __floordiv__(self, other):
        if isinstance(other, SignedNumber):
            return SignedNumber(self.value // other.value)
        elif isinstance(other, (int, float)):
            return SignedNumber(self.value // other)
        else:
            return NotImplemented

a = SignedNumber(-7)
b = SignedNumber(3)
print(a // b)  # Output: -3 (not -2)
print(a // -3) # Output: 2 (not 3)

此示例显示了地板除法如何向负无穷大方向舍入,这与常规除法不同。 -7 // 3 等于 -3,而不是 -2。

该实现保留了 Python 的标准地板除法行为,这对于保持与内置数值类型的一致性非常重要。

最佳实践

资料来源

作者

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

列出所有 Python 教程