在Python中,特殊类(通常指包含特殊方法的类)是实现面向对象编程和操作符重载的核心。这些特殊方法以双下划线开头和结尾(如 __init__),让自定义类能够与Python内置功能无缝集成。

核心特殊方法分类

1. 构造与析构方法

class MyClass:
    def __new__(cls, *args, **kwargs):
        """创建实例时第一个调用的方法,返回实例对象"""
        instance = super().__new__(cls)
        return instance
    
    def __init__(self, value):
        """初始化实例属性"""
        self.value = value
        print(f"初始化完成,值为: {value}")
    
    def __del__(self):
        """对象被销毁时调用"""
        print(f"对象 {self} 被销毁")

2. 字符串表示方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def __str__(self):
        """用户友好的字符串表示"""
        return f"Person(name={self.name}, age={self.age})"
    
    def __repr__(self):
        """开发者友好的字符串表示,通常可用于重建对象"""
        return f"Person('{self.name}', {self.age})"
    
    def __format__(self, format_spec):
        """支持格式化输出"""
        if format_spec == "verbose":
            return f"{self.name} is {self.age} years old"
        return str(self)

# 使用示例
p = Person("Alice", 30)
print(str(p))    # Person(name=Alice, age=30)
print(repr(p))   # Person('Alice', 30)
print(f"{p:verbose}")  # Alice is 30 years old

3. 比较操作符重载

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __eq__(self, other):
        """等于 == """
        if not isinstance(other, Vector):
            return False
        return self.x == other.x and self.y == other.y
    
    def __lt__(self, other):
        """小于 < (基于向量长度)"""
        if not isinstance(other, Vector):
            return NotImplemented
        return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)
    
    def __le__(self, other):
        """小于等于 <="""
        return self < other or self == other
    
    # 类似地可以定义 __gt__, __ge__, __ne__

# 使用示例
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 == v2)  # False
print(v1 < v2)   # True

4. 算术操作符重载

class ComplexNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag
    
    def __add__(self, other):
        """加法 + """
        if isinstance(other, ComplexNumber):
            return ComplexNumber(self.real + other.real, 
                                self.imag + other.imag)
        return ComplexNumber(self.real + other, self.imag)
    
    def __sub__(self, other):
        """减法 - """
        if isinstance(other, ComplexNumber):
            return ComplexNumber(self.real - other.real, 
                                self.imag - other.imag)
        return ComplexNumber(self.real - other, self.imag)
    
    def __mul__(self, other):
        """乘法 * """
        if isinstance(other, ComplexNumber):
            real = self.real * other.real - self.imag * other.imag
            imag = self.real * other.imag + self.imag * other.real
            return ComplexNumber(real, imag)
        return ComplexNumber(self.real * other, self.imag * other)
    
    def __radd__(self, other):
        """右侧加法,处理 other + self 的情况"""
        return self + other

# 使用示例
c1 = ComplexNumber(1, 2)
c2 = ComplexNumber(3, 4)
print((c1 + c2).real, (c1 + c2).imag)  # 4, 6

5. 容器类方法

class CustomList:
    def __init__(self, *args):
        self._data = list(args)
    
    def __getitem__(self, index):
        """获取元素 list[index]"""
        return self._data[index]
    
    def __setitem__(self, index, value):
        """设置元素 list[index] = value"""
        self._data[index] = value
    
    def __delitem__(self, index):
        """删除元素 del list[index]"""
        del self._data[index]
    
    def __len__(self):
        """返回长度 len(list)"""
        return len(self._data)
    
    def __contains__(self, item):
        """检查包含关系 item in list"""
        return item in self._data
    
    def __iter__(self):
        """返回迭代器"""
        return iter(self._data)

# 使用示例
cl = CustomList(1, 2, 3, 4, 5)
print(len(cl))        # 5
print(cl[2])          # 3
print(3 in cl)        # True

6. 可调用对象

class Adder:
    def __init__(self, base):
        self.base = base
    
    def __call__(self, x):
        """使实例可以像函数一样调用"""
        return self.base + x

# 使用示例
add5 = Adder(5)
print(add5(10))  # 15

7. 上下文管理器

class FileManager:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.file = None
    
    def __enter__(self):
        """进入上下文时调用"""
        self.file = open(self.filename, self.mode)
        return self.file
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时调用"""
        if self.file:
            self.file.close()
        if exc_type:
            print(f"异常发生: {exc_type}")
        return False  # 不抑制异常

# 使用示例
with FileManager("test.txt", "w") as f:
    f.write("Hello, World!")

8. 属性访问控制

class ProtectedClass:
    def __init__(self):
        self._protected = "protected"
        self.__private = "private"
    
    def __getattribute__(self, name):
        """属性访问拦截"""
        print(f"访问属性: {name}")
        return super().__getattribute__(name)
    
    def __setattr__(self, name, value):
        """属性设置拦截"""
        print(f"设置属性: {name} = {value}")
        super().__setattr__(name, value)
    
    def __getattr__(self, name):
        """访问不存在的属性时调用"""
        return f"属性 {name} 不存在"

# 使用示例
obj = ProtectedClass()
print(obj._protected)  # 先打印"访问属性: _protected",然后返回"protected"
print(obj.nonexistent) # 返回"属性 nonexistent 不存在"

实际应用示例:实现一个智能分数类

class Fraction:
    """实现分数运算的类"""
    
    def __init__(self, numerator, denominator=1):
        if denominator == 0:
            raise ValueError("分母不能为零")
        
        # 约分
        gcd_val = self._gcd(abs(numerator), abs(denominator))
        self.numerator = numerator // gcd_val
        self.denominator = denominator // gcd_val
        
        # 确保分母为正
        if self.denominator < 0:
            self.numerator = -self.numerator
            self.denominator = -self.denominator
    
    @staticmethod
    def _gcd(a, b):
        """计算最大公约数"""
        while b:
            a, b = b, a % b
        return a
    
    def __add__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        common_denominator = self.denominator * other.denominator
        new_numerator = (self.numerator * other.denominator + 
                        other.numerator * self.denominator)
        return Fraction(new_numerator, common_denominator)
    
    def __sub__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        common_denominator = self.denominator * other.denominator
        new_numerator = (self.numerator * other.denominator - 
                        other.numerator * self.denominator)
        return Fraction(new_numerator, common_denominator)
    
    def __mul__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        return Fraction(self.numerator * other.numerator,
                       self.denominator * other.denominator)
    
    def __truediv__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        return Fraction(self.numerator * other.denominator,
                       self.denominator * other.numerator)
    
    def __eq__(self, other):
        if isinstance(other, int):
            other = Fraction(other)
        return (self.numerator == other.numerator and 
                self.denominator == other.denominator)
    
    def __str__(self):
        if self.denominator == 1:
            return str(self.numerator)
        return f"{self.numerator}/{self.denominator}"
    
    def __repr__(self):
        return f"Fraction({self.numerator}, {self.denominator})"

# 使用示例
f1 = Fraction(1, 2)
f2 = Fraction(3, 4)
print(f1 + f2)  # 5/4
print(f1 * f2)  # 3/8
print(f1 == Fraction(2, 4))  # True

最佳实践建议

  1. 保持一致性:重载操作符时,确保行为与内置类型一致
  2. 适当使用NotImplemented:当操作不支持时返回NotImplemented
  3. 考虑性能:特殊方法可能被频繁调用,应保持高效
  4. 文档化:为所有特殊方法提供清晰的文档说明
  5. 测试覆盖:确保所有特殊方法都经过充分测试

掌握这些特殊方法的使用,能够让你创建出更加Pythonic、功能强大的自定义类。