Bootstrap

Python中的魔术方法(双下方法或特殊方法)介绍


Python中的魔术方法(也称为双下方法或特殊方法)是一些有特殊意义的名字,它们可以被重写以改变类的行为。这些方法通常在对象的生命周期中的特定时间点被 Python解释器自动调用。以下是一些常用的魔术方法的总结:

魔术方法介绍

实例创建和初始化
  • __new__(cls, ...): 创建实例时调用,返回一个实例。
  • __init__(self, ...): 初始化实例时调用。
  • __del__(self): 实例被销毁时调用,用于清理资源。
属性访问
  • __getattr__(self, name): 访问不存在的属性时调用。
  • __setattr__(self, name, value): 设置属性值时调用。
  • __delattr__(self, name): 删除属性时调用。
  • __getattribute__(self, name): 访问属性时调用,比 __getattr__ 更早。
描述符协议
  • __get__(self, instance, owner): 获取值时调用。
  • __set__(self, instance, value): 设置值时调用。
  • __delete__(self, instance): 删除值时调用。
迭代器和生成器
  • __iter__(self): 返回迭代器。
  • __next__(self): 返回容器的下一个元素。
  • __reversed__(self): 返回容器的反向迭代器。
容器类型
  • __len__(self): 返回容器长度。
  • __getitem__(self, key): 获取容器元素。
  • __setitem__(self, key, value): 设置容器元素。
  • __delitem__(self, key): 删除容器元素。
  • __contains__(self, item): 检查容器是否包含某个元素。
类型转换和表示
  • __repr__(self): 返回对象的“官方”字符串表示,用于调试。
  • __str__(self): 返回对象的“信息性”字符串表示,用于打印。
  • __bytes__(self): 返回对象的字节串表示。
  • __bool__(self): 返回对象的布尔值。
  • __format__(self, format_spec): 用于格式化对象。
  • __hash__(self): 返回对象的哈希值。
  • __int__(self), __float__(self), etc.: 类型转换方法。
比较操作
  • __lt__(self, other), __le__(self, other), __eq__(self, other), __ne__(self, other), __gt__(self, other), __ge__(self, other): 比较操作符。
  • __cmp__(self, other): 用于比较的旧方法,已废弃。
数学操作
  • __add__(self, other), __sub__(self, other), __mul__(self, other), __truediv__(self, other), __floordiv__(self, other), __mod__(self, other), etc.: 数学操作符。
  • __pow__(self, other, mod): 幂运算。
  • __neg__(self), __pos__(self), __abs__(self), etc.: 一元操作符。
通用操作
  • __round__(self, ndigits): 四舍五入操作。
  • __copy__(self): 浅拷贝。
  • __deepcopy__(self, memo): 深拷贝。
属性定义
  • __slots__: 用于限制实例属性,优化内存使用。
元类和类创建
  • __prepare__(name, bases, **kwds): 在类创建前,返回一个用于构造类的映射。
  • __new__(cls, name, bases, namespace, **kwds): 创建类时调用。
  • __init__(self, name, bases, namespace, **kwds): 类创建后调用。
特殊方法的使用

这些特殊方法可以被重写以改变类的行为,但是它们必须严格遵守特定的协议。例如,__eq__ 方法必须返回一个布尔值,__len__ 方法必须返回一个整数,等等。

使用这些特殊方法时,通常不需要调用它们的父类实现,除非你想要扩展而不是完全替换它们的行为。正确地使用这些方法可以提供强大的功能,例如自定义对象的比较、算术操作、字符串表示等。

魔术方法实例

__init____new__

__init__ 是初始化方法,而 __new__ 是创建实例的方法。

class Student:
    def __new__(cls, name):
        print("Creating student object.")
        return super().__new__(cls)

    def __init__(self, name):
        self.name = name

s = Student("Alice")

输出:

Creating student object.
__str____repr__

__str__ 是返回对象的“信息性”字符串表示,而 __repr__ 是返回对象的“官方”字符串表示。

class Student:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"Student: {self.name}"

    def __repr__(self):
        return f"Student('{self.name}')"

s = Student("Alice")
print(str(s))  # Student: Alice
print(repr(s))  # Student('Alice')
__iter____next__

__iter__ 返回迭代器,__next__ 返回容器的下一个元素。

class Counter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def __next__(self):
        if self.current > self.high:
            raise StopIteration
        else:
            num = self.current
            self.current += 1
            return num

counter = Counter(1, 3)
for number in counter:
    print(number)

输出:

1
2
3
__len____getitem__

__len__ 返回容器长度,__getitem__ 获取容器元素。

class Fibonacci:
    def __init__(self):
        self.numbers = [0, 1]

    def __len__(self):
        return len(self.numbers)

    def __getitem__(self, index):
        while index >= len(self.numbers):
            self.numbers.append(self.numbers[-1] + self.numbers[-2])
        return self.numbers[index]

fib = Fibonacci()
print(len(fib))  # 2
print(fib[0])    # 0
print(fib[1])    # 1
print(fib[2])    # 1
print(fib[3])    # 2
__eq____lt__

__eq__ 比较两个对象是否相等,__lt__ 比较两个对象的大小。

class Person:
    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return self.name == other.name

    def __lt__(self, other):
        return self.name < other.name

p1 = Person("Alice")
p2 = Person("Bob")
p3 = Person("Alice")

print(p1 == p3)  # True
print(p1 < p2)   # True
__call__

__call__ 允许一个实例像函数那样被调用。

class Greeting:
    def __init__(self, message):
        self.message = message

    def __call__(self):
        print(self.message)

greet = Greeting("Hello, World!")
greet()  # Hello, World!
__format__

__format__ 用于格式化对象。

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __format__(self, spec):
        if spec == 'polar':
            radius = (self.x ** 2 + self.y ** 2) ** 0.5
            theta = (self.y / radius) * 180 / 3.14159 if radius else 0
            return f"Polar({radius:.2f}, {theta:.2f})"
        else:
            return f"Cartesian({self.x:.2f}, {self.y:.2f})"

p = Point(3, 4)
print(f"{p:polar}")  # Polar(5.00, 53.13)
print(f"{p}")        # Cartesian(3.00, 4.00)

这些示例展示了如何使用Python中的魔术方法来扩展和自定义类的行为。通过重写这些方法,你可以实现复杂的对象行为和交互模式。

;