在Python中,方法名以双下划线__
开头的成员被称为特殊方法(Special Method Names)或魔术方法(Magic Methods)。这些方法在Python中具有特殊的意义和用途,它们主要用来实现Python内置的行为,例如:
-
对象的生命周期管理:
__init__
:对象初始化方法,当创建一个类的实例时自动调用。__del__
:对象析构方法,当对象被垃圾收集器回收时调用(但并非总是保证会被调用)。
-
对象表示和转换:
__str__
:返回对象的字符串表示,通常用于打印或转化为字符串时。__repr__
:返回对象的官方字符串表示,通常用于调试和开发者之间的沟通。__bytes__
,__format__
,__hash__
等也是类似的转化方法。
-
运算符重载:
__add__
,__sub__
,__mul__
,__eq__
,__lt__
等,用于实现对+、-、*、==、<等运算符的支持。
-
上下文管理:
__enter__
和__exit__
用于实现上下文管理协议,配合with
语句使用。
-
属性访问控制:
__getattr__
,__setattr__
,__getattribute__
,__delattr__
等方法,用于控制对对象属性的访问。
-
类方法和静态方法:
__new__
:控制类实例的创建过程,通常用于实现单例模式、自定义实例化流程等。__call__
:使类实例或类本身可以像函数一样被调用。
-
类和元类相关:
__metaclass__
(在Python 3中被元类语法取代)和元类中的__prepare__
,__new__
,__init__
等方法,用于控制类的创建。
总之,这些特殊方法的存在使得程序员能够自定义类的行为,使其在某些特定情况下表现得像内建类型一样,增强代码的表达力和灵活性。
需要注意的是,
- 以双下划线开头和结尾的特殊方法(如
__foo__
)通常用于Python内部的命名空间管理和其他语言层面的特有操作。 - 而仅仅以双下划线开头的(如
__bar
)则可能会被Python解释器改写名称以防止与其他模块中的名称冲突,这一特性被称为名称修饰(name mangling),但它并不影响全局查找,主要用于类的内部实现细节。
Python中的魔术方法非常丰富,下面列举一些最常用和相对不那么常用的魔术方法,并给出相应的简要说明与代码示例:
常用魔术方法:
-
初始化与析构
-
__init__(self, ...)
: 实例化时调用,初始化对象属性。class Person: def __init__(self, name, age): self.name = name self.age = age p = Person('Alice', 30)
-
__del__(self)
: 对象被垃圾回收前调用,但并不保证一定会执行。class Resource: def __init__(self): print("Resource created.") def __del__(self): print("Resource destroyed.") r = Resource() del r # 如果r此时没有其他引用,将会输出 "Resource destroyed."
-
-
对象转换
-
__str__(self)
: 返回便于人阅读的对象表示。class Book: def __init__(self, title): self.title = title def __str__(self): return f"Book titled: {self.title}" b = Book("Pride and Prejudice") print(b) # 输出: Book titled: Pride and Prejudice
-
__repr__(self)
: 用于调试,返回一个官方的、可能包含更多详细信息的字符串表示。class Book: def __init__(self, title, author, pages): self.title = title self.author = author self.pages = pages def __repr__(self): return f"Book(title='{self.title}', author='{self.author}', pages={self.pages})" b = Book("The Catcher in the Rye", "J.D. Salinger", 277) print(repr(b)) # 输出: Book(title='The Catcher in the Rye', author='J.D. Salinger', pages=277)
-
-
运算符重载
__add__(self, other)
: 定义加法操作。class Vector: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) v1 = Vector(1, 2) v2 = Vector(3, 4) result = v1 + v2
-
比较操作符
__eq__(self, other)
: 定义等于操作。class Point: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): return self.x == other.x and self.y == other.y p1 = Point(1, 2) p2 = Point(1, 2) assert p1 == p2
-
迭代和序列化
-
__iter__(self)
: 定义可迭代对象。class MyRange: def __init__(self, start, end): self.start = start self.end = end def __iter__(self): return iter(range(self.start, self.end)) my_range = MyRange(1, 5) for i in my_range: print(i) # 输出: 1, 2, 3, 4
-
__getitem__(self, key)
: 支持索引访问。class Matrix: def __init__(self, data): self.data = data def __getitem__(self, index): return self.data[index] m = Matrix([[1, 2], [3, 4]]) print(m[0][1]) # 输出: 2
-
相对不常用但重要的魔术方法:
-
属性访问控制
__getattr__(self, name)
: 当试图获取一个不存在的属性时调用。class MyClass: def __getattr__(self, attr): if attr == 'secret': return "This is a secret attribute!" else: raise AttributeError(f"'MyClass' object has no attribute '{attr}'") obj = MyClass() print(obj.secret) # 输出: This is a secret attribute!
-
描述符协议
__get__(self, instance, owner)
和__set__(self, instance, value)
: 创建属性描述符。class Descriptor: def __init__(self, default): self.value = default def __get__(self, instance, owner): return self.value def __set__(self, instance, value): self.value = value class MyClass: attr_descriptor = Descriptor('default') obj = MyClass() print(obj.attr_descriptor) # 输出: default obj.attr_descriptor = 'new value' print(MyClass.attr_descriptor.value) # 输出: new value
-
元类相关
__new__(cls[, ...])
: 控制类实例的创建过程,在__init__
之前调用。
class Singleton(type):
_instances = {}
def __new__(cls, name, bases, attrs, *args, **kwargs):
if cls not in cls._instances:
instance = super().__new__(cls, name, bases, attrs, *args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class MyClass(metaclass=Singleton):
pass
a = MyClass()
b = MyClass()
assert a is b # 确保只有一个实例
- 上下文管理器
__enter__(self)
和__exit__(self, exc_type, exc_value, traceback)
: 用于实现with
语句。class FileContextManager: def __init__(self, filename): self.file = open(filename, 'r') def __enter__(self): return self.file def __exit__(self, exc_type, exc_value, traceback): self.file.close() with FileContextManager('example.txt') as f: content = f.read()
以上只列出了一部分常用的和不常用但关键的魔术方法,实际Python中还有很多其他魔术方法,根据具体的场景和需求来选择使用。为了深入了解,建议查阅Python官方文档以获取完整列表和详细说明。