ZetCode

Python __ifloordiv__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨 Python 的 __ifloordiv__ 方法,这是用于原地整除的特殊方法。我们将涵盖基本用法、运算符重载、实际示例和常见用例。

基本定义

__ifloordiv__ 方法实现原地整除运算 (//=)。它原地修改左操作数,而不是创建一个新对象。

关键特性:它必须返回修改后的对象,执行整除运算,并在使用 //= 运算符时调用。 它是 __floordiv__ 的原地版本。

基本的 __ifloordiv__ 实现

这是一个简单的实现,展示了 __ifloordiv__ 如何与自定义类一起工作。 它演示了基本的原地整除行为。

basic_ifloordiv.py
class Number:
    def __init__(self, value):
        self.value = value
    
    def __ifloordiv__(self, other):
        self.value //= other
        return self
    
    def __repr__(self):
        return f"Number({self.value})"

num = Number(10)
num //= 3
print(num)  # Output: Number(3)

此示例显示了一个实现原地整除的 Number 类。 //= 运算符直接修改实例的值。

该方法修改 self.value 并返回 self,这是原地操作在所有上下文中正确工作所必需的。

处理不同的右操作数类型

__ifloordiv__ 可以处理各种右操作数类型。 此示例展示了如何实现类型检查和转换。

type_handling.py
class Container:
    def __init__(self, items):
        self.items = items
    
    def __ifloordiv__(self, other):
        if isinstance(other, int):
            self.items = self.items[::other]
        elif isinstance(other, Container):
            self.items = [x//y for x, y in zip(self.items, other.items)]
        else:
            raise TypeError("Unsupported operand type")
        return self
    
    def __repr__(self):
        return f"Container({self.items})"

c1 = Container([10, 20, 30, 40, 50])
c1 //= 2  # Take every 2nd item
print(c1)  # Container([10, 30, 50])

c2 = Container([5, 10, 15])
c1 //= c2  # Element-wise floor division
print(c1)  # Container([2, 3, 3])

Container 类为 //= 实现了两种不同的行为:当右操作数为整数时进行切片,当它为另一个 Container 时进行元素级除法。

该示例演示了 __ifloordiv__ 如何根据操作数类型提供不同的功能,使其非常灵活。

继承和 __ifloordiv__

从内置类型继承时,您可能需要实现 __ifloordiv__ 以保持预期的行为。 这是一个自定义列表的示例。

inheritance.py
class DivisibleList(list):
    def __ifloordiv__(self, divisor):
        for i in range(len(self)):
            self[i] //= divisor
        return self
    
    def __floordiv__(self, divisor):
        return DivisibleList([x // divisor for x in self])

nums = DivisibleList([10, 20, 30, 40, 50])
nums //= 3
print(nums)  # [3, 6, 10, 13, 16]

result = nums // 2
print(result)  # [1, 3, 5, 6, 8]
print(type(result))  # <class '__main__.DivisibleList'>

DivisibleList 类继承自 list 并添加原地和常规整除运算。 //= 运算符原地修改列表。

请注意,我们还为常规整除运算 (//) 实现了 __floordiv__,它返回一个新实例而不是修改现有的实例。

矩阵整除

对于数学应用程序,__ifloordiv__ 可以实现矩阵整除。 此示例显示了一个简单的矩阵实现。

matrix.py
class Matrix:
    def __init__(self, data):
        self.data = data
    
    def __ifloordiv__(self, other):
        if isinstance(other, (int, float)):
            for row in self.data:
                for i in range(len(row)):
                    row[i] //= other
        elif isinstance(other, Matrix):
            for i in range(len(self.data)):
                for j in range(len(self.data[i])):
                    self.data[i][j] //= other.data[i][j]
        return self
    
    def __repr__(self):
        return '\n'.join(' '.join(map(str, row)) for row in self.data)

m = Matrix([[10, 20], [30, 40]])
m //= 3
print(m)
# Output:
# 3 6
# 10 13

Matrix 类实现了标量值和其他矩阵的原地整除。 该操作直接修改矩阵元素。

该实现检查操作数类型,并执行与标量的元素级除法,或者与具有相同尺寸的另一个矩阵的元素级除法。

带 __ifloordiv__ 的分数类

对于更复杂的示例,这是一个 Fraction 类,它实现原地整除,同时保持最简形式。

fraction.py
from math import gcd

class Fraction:
    def __init__(self, numerator, denominator=1):
        common = gcd(numerator, denominator)
        self.n = numerator // common
        self.d = denominator // common
    
    def __ifloordiv__(self, other):
        if isinstance(other, int):
            self.n //= other
        elif isinstance(other, Fraction):
            self.n = (self.n * other.d) // (self.d * other.n)
            self.d = 1
        else:
            raise TypeError("Unsupported operand type")
        common = gcd(self.n, self.d)
        self.n //= common
        self.d //= common
        return self
    
    def __repr__(self):
        return f"Fraction({self.n}, {self.d})"

f = Fraction(10, 3)
f //= 2
print(f)  # Fraction(1, 1)

Fraction 类以最简形式维护分数,并实现与整数和其他分数的原地整除。

当除以另一个分数时,它将运算转换为乘以倒数,然后执行整除,最后简化结果。

最佳实践

资料来源

作者

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

列出所有 Python 教程