ZetCode

Python __divmod__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南将探讨 Python 的 __divmod__ 方法,这是实现内置 divmod() 函数的特殊方法。我们将介绍基本用法、数字运算、自定义实现和实际示例。

基本定义

__divmod__ 方法是一个实现 divmod() 内置函数的特殊方法。它返回一个包含两个数字相除时的商和余数的元组。

关键特征:它接受两个参数(self 和 other),返回一个包含两个值(商、余数)的元组,并由 divmod() 函数调用。它必须为数字类型实现,以支持此操作。

基本 __divmod__ 实现

这是一个简单的实现,展示了 __divmod__ 如何与内置数字类型一起工作。它演示了该方法的基本行为。

basic_divmod.py
x = 10
y = 3
result = divmod(x, y)
print(result)  # Output: (3, 1)

# Equivalent to:
print((x // y, x % y))

此示例显示了整数的标准行为。divmod() 函数返回一个元组,其中包含 10 除以 3 的商(3)和余数(1)。

当在实现它的对象上使用 divmod() 时,__divmod__ 方法会在后台被调用。对于内置类型,这已经提供了。

具有 __divmod__ 的自定义类

我们可以在自定义类中实现 __divmod__ 来支持 divmod() 操作。这是一个自定义数字类的示例。

custom_divmod.py
class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __divmod__(self, other):
        quotient = self.value // other.value
        remainder = self.value % other.value
        return (quotient, remainder)

a = MyNumber(17)
b = MyNumber(5)
print(divmod(a, b))  # Output: (3, 2)

这个自定义数字类实现了 __divmod__ 来支持 divmod() 操作。它对存储的值执行整数除法和模运算。

该实现返回一个包含商和余数的元组,与内置数字类型的行为相匹配。这使得该类能够与 Python 的数字运算无缝协作。

使用 __divmod__ 进行浮点数除法

__divmod__ 方法也适用于浮点数,尽管由于浮点精度,结果可能不太直观。

float_divmod.py
x = 10.5
y = 3.2
result = divmod(x, y)
print(result)  # Output: (3.0, 0.8999999999999995)

# Explanation:
# 3.2 * 3 = 9.6
# 10.5 - 9.6 = 0.9 (with floating point precision error)

此示例演示了浮点数的 divmod()。商为 3.0,余数约等于 0.9(存在浮点精度误差)。

请注意,浮点运算可能会引入小的精度误差,如余数计算所示。这在计算机中是浮点表示的固有特性。

带 __divmod__ 的负数

__divmod__ 方法与负数一起使用的行为遵循 Python 的除法规则,这可能与数学预期不同。

negative_divmod.py
# Positive dividend, negative divisor
print(divmod(10, -3))  # Output: (-4, -2)

# Negative dividend, positive divisor
print(divmod(-10, 3))  # Output: (-4, 2)

# Negative dividend and divisor
print(divmod(-10, -3))  # Output: (3, -1)

这些示例展示了 divmod() 如何处理负数。结果保持不变:divmod(a, b)[1]b 具有相同的符号。

商始终向负无穷大舍入,余数与除数具有相同的符号。这是 Python 对除法和模运算的标准行为。

返回不同类型的自定义 __divmod__

__divmod__ 方法可以返回任何类型,而不仅仅是数字元组。这是一个返回自定义结果对象的示例。

custom_result.py
class DivModResult:
    def __init__(self, quotient, remainder):
        self.quotient = quotient
        self.remainder = remainder
    
    def __repr__(self):
        return f"Result(q={self.quotient}, r={self.remainder})"

class MyNumber:
    def __init__(self, value):
        self.value = value
    
    def __divmod__(self, other):
        q = self.value // other.value
        r = self.value % other.value
        return DivModResult(q, r)

a = MyNumber(17)
b = MyNumber(5)
result = divmod(a, b)
print(result)  # Output: Result(q=3, r=2)

此示例展示了一个自定义的 __divmod__ 实现,它返回一个专门的结果对象而不是元组。DivModResult 类将商和余数存储为属性。

虽然这是可能的,但为了与内置类型和用户期望保持一致,通常建议遵循 Python 返回元组的约定。

最佳实践

资料来源

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出所有 Python 教程