ZetCode

Python __pow__ 方法

最后修改于 2025 年 4 月 8 日

这份全面的指南探讨了 Python 的 __pow__ 方法,这是一个实现幂/指数运算的特殊方法。我们将介绍基本用法、三参数形式、数学自定义和示例。

基本定义

__pow__ 方法用于实现幂/指数运算 (** 运算符)。它允许对象定义自己的幂运算行为。

主要特点:它至少接受两个参数(self 和指数),可以接受一个可选的第三个参数作为模数,并且应该返回幂运算的结果。它是 Python 运算符重载系统的一部分。

基本 __pow__ 实现

这是一个简单的实现,展示了 __pow__ 如何与 ** 运算符一起工作。此示例创建了一个数字包装类。

basic_pow.py
class PowerNumber:
    def __init__(self, value):
        self.value = value
    
    def __pow__(self, exponent):
        print("__pow__ called")
        return self.value ** exponent

num = PowerNumber(3)
result = num ** 4  # Calls __pow__
print(result)  # Output: 81

此示例显示了基本的幂运算。当 ** 与 PowerNumber 实例一起使用时,Python 会调用 __pow__ 并传入指数。

该方法返回存储值提升到给定幂的结果。 这允许为用户定义的对象提供自定义的幂行为。

三参数幂运算

__pow__ 还可以实现 pow() 的三参数形式,其中包括用于模幂运算的模数参数。

three_arg_pow.py
class ModularNumber:
    def __init__(self, value):
        self.value = value
    
    def __pow__(self, exponent, modulus=None):
        print("__pow__ called with modulus" if modulus else "__pow__ called")
        if modulus is not None:
            return pow(self.value, exponent, modulus)
        return self.value ** exponent

num = ModularNumber(5)
print(num ** 3)  # 125
print(pow(num, 3, 7))  # 6 (125 % 7)

此实现处理双参数和三参数幂运算。模数参数是可选的,默认为 None。

当使用内置的 pow() 且带有三个参数时,Python 会调用 __pow__ 并传入模数参数。 这可以实现有效的模幂运算。

反向幂运算 __rpow__

当左操作数不支持幂运算时,Python 会检查右操作数上的 __rpow__。 这称为“反射幂”。

reverse_pow.py
class ReversePower:
    def __rpow__(self, base):
        print("__rpow__ called")
        return base ** 2  # Always squares the base

rp = ReversePower()
result = 5 ** rp  # Calls __rpow__
print(result)  # 25

此示例显示了当左操作数(在本例中为 5)不知道如何处理与我们类的幂运算时,如何调用 __rpow__

该方法接收基数作为其第一个参数,并返回运算结果。 这使得可以将内置类型放在左侧进行幂运算。

矩阵指数

__pow__ 可以实现矩阵指数运算,其中矩阵通过重复相乘来提升到整数幂。

matrix_pow.py
class Matrix:
    def __init__(self, data):
        self.data = data
    
    def __mul__(self, other):
        # Simple matrix multiplication (for illustration)
        return Matrix([[sum(a*b for a,b in zip(row, col)) 
                       for col in zip(*other.data)] 
                       for row in self.data])
    
    def __pow__(self, exponent):
        if not isinstance(exponent, int) or exponent < 0:
            raise ValueError("Exponent must be non-negative integer")
        result = Matrix([[1 if i == j else 0 for j in range(len(self.data))]
                        for i in range(len(self.data))])  # Identity matrix
        for _ in range(exponent):
            result = result * self
        return result
    
    def __repr__(self):
        return str(self.data)

m = Matrix([[1, 2], [3, 4]])
print(m ** 2)  # [[7, 10], [15, 22]]

此矩阵类通过重复相乘来实现指数运算。__pow__ 方法检查有效的指数,并使用单位矩阵作为起点。

矩阵指数在许多数学和科学计算应用中很有用,特别是对于线性变换。

自定义数学运算

__pow__ 可以定义非标准的幂运算,例如容器类的按元素指数运算或其他数学运算。

custom_pow.py
class Vector:
    def __init__(self, values):
        self.values = values
    
    def __pow__(self, exponent):
        if isinstance(exponent, (int, float)):
            return Vector([x ** exponent for x in self.values])
        elif isinstance(exponent, Vector):
            return Vector([x ** y for x, y in zip(self.values, exponent.values)])
        else:
            raise TypeError("Unsupported exponent type")
    
    def __repr__(self):
        return f"Vector({self.values})"

v1 = Vector([2, 3, 4])
print(v1 ** 2)  # Vector([4, 9, 16])
print(v1 ** Vector([1, 2, 3]))  # Vector([2, 9, 64])

此 Vector 类实现按元素指数运算。它处理标量指数(应用于每个元素)和向量指数(按元素)。

该方法包括类型检查,以确保指数是数字或另一个 Vector,否则会引发 TypeError 异常。

最佳实践

资料来源

作者

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

列出所有 Python 教程