文章目录
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
中的魔术方法来扩展和自定义类的行为。通过重写这些方法,你可以实现复杂的对象行为和交互模式。