ZetCode

Python __invert__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨 Python 的 __invert__ 方法,这是一个实现按位非运算的特殊方法。我们将介绍基本用法、自定义实现、实际示例和常见用例。

基本定义

__invert__ 方法是 Python 中的一个特殊方法,用于实现按位非运算 (~)。当对一个对象使用一元 ~ 运算符时,它会被调用。

主要特点:它只接受 self 作为参数,返回反转后的值,并且可以被重写以自定义自定义类的行为。它是 Python 的运算符重载方法之一。

基本 __invert__ 实现

这是一个简单的实现,展示了 __invert__ 如何处理整数和自定义类。它演示了基本的语法和行为。

basic_invert.py
class BitwiseNumber:
    def __init__(self, value):
        self.value = value
    
    def __invert__(self):
        return BitwiseNumber(~self.value)
    
    def __repr__(self):
        return f"BitwiseNumber({self.value})"

num = BitwiseNumber(5)
inverted = ~num
print(inverted)  # BitwiseNumber(-6)

此示例显示了一个实现了 __invert__ 的自定义类。当我们使用 ~ 运算符时,Python 会调用此方法。对于整数,~x 等于 -(x+1)。

该方法返回一个新的实例,而不是修改现有的实例。这遵循了 Python 为操作返回新对象的约定。

自定义位掩码实现

__invert__ 对于处理位掩码和标志非常有用。这里我们创建一个自定义的 Flags 类,它使用反转来进行标志操作。

flags.py
class Flags:
    def __init__(self, value=0):
        self.value = value
    
    def __invert__(self):
        return Flags(~self.value)
    
    def __or__(self, other):
        return Flags(self.value | other.value)
    
    def __and__(self, other):
        return Flags(self.value & other.value)
    
    def __repr__(self):
        return f"Flags({bin(self.value)})"

READ = Flags(0b001)
WRITE = Flags(0b010)
EXECUTE = Flags(0b100)

permissions = READ | WRITE
print(~permissions)  # Inverts all bits

这个 Flags 类实现了几个按位运算。__invert__ 方法翻转值中的所有位。与其他运算符结合使用,它可以创建一个强大的位掩码系统。

反转运算对于创建掩码补码或在位掩码运算中切换标志状态特别有用。

矩阵求逆实现

我们可以将 __invert__ 重新用于非按位运算。在这里,我们在线性代数上下文中将其用于矩阵求逆。

matrix.py
class Matrix:
    def __init__(self, data):
        self.data = data
    
    def __invert__(self):
        # Simple 2x2 matrix inversion
        a, b = self.data[0]
        c, d = self.data[1]
        det = a * d - b * c
        return Matrix([
            [d/det, -b/det],
            [-c/det, a/det]
        ])
    
    def __repr__(self):
        return f"Matrix({self.data})"

m = Matrix([[4, 7], [2, 6]])
inverse = ~m
print(inverse)  # Inverted matrix

此示例展示了 __invert__ 用于矩阵求逆的一种非常规但有效的用法。虽然 ~ 通常表示按位非,但 Python 允许创造性的运算符重载。

请注意,这种用法可能会混淆期望按位运算的用户。以这种方式重新利用运算符时,清晰的文档至关重要。

自定义数字系统的二进制补码

在这里,我们实现了一个自定义的二进制数字系统,其中 __invert__ 返回我们自定义数字的 1 的补码(按位取反)。

binary.py
class Binary:
    def __init__(self, value, bits=8):
        self.value = value
        self.bits = bits
    
    def __invert__(self):
        mask = (1 << self.bits) - 1
        return Binary((~self.value) & mask, self.bits)
    
    def __repr__(self):
        return f"Binary({bin(self.value)}, bits={self.bits})"

num = Binary(0b1010, bits=4)
print(~num)  # Binary(0b0101, bits=4)

这个 Binary 类维护一个固定的位宽。__invert__ 实现确保结果使用掩码保持在指定的位范围内。

掩码操作可防止 Python 的无限精度整数在反转时产生意外的大负数。

安全角色反转

在这个以安全为中心的示例中,我们使用 __invert__ 返回一个具有反转权限的角色,用于测试目的。

security.py
class Role:
    def __init__(self, read=False, write=False, execute=False):
        self.read = read
        self.write = write
        self.execute = execute
    
    def __invert__(self):
        return Role(
            not self.read,
            not self.write,
            not self.execute
        )
    
    def __repr__(self):
        return f"Role(r={self.read}, w={self.write}, x={self.execute})"

admin = Role(True, True, True)
no_access = ~admin
print(no_access)  # Role with all False

这个 Role 类使用 __invert__ 创建一个具有相反权限的角色。这对于安全测试以验证拒绝访问非常有用。

虽然非常规,但这演示了 __invert__ 如何在适当记录的情况下表示超出按位运算的逻辑反转。

最佳实践

资料来源

作者

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

列出所有 Python 教程