文章目录
- 方法名 功能描述 示例 __init__ 构造函数,初始化对象 obj = MyClass() __str__ 返回用户友好的字符串表示 print(obj) __repr__ 返回开发者友好的字符串表示 repr(obj) __len__ 返回容器长度 len(obj) class Book: def __init__(self, title, author, pages): self.title = title self.author = author self.pages = pages def __str__(self): return f”‘{self.title}’ by {self.author}” def __repr__(self): return f”Book(title='{self.title}’, author='{self.author}’)” def __len__(self): return self.pages book = Book(“Python Crash Course”, “Eric Matthes”, 544) print(book) # ‘Python Crash Course’ by Eric Matthes print(repr(book)) # Book(title=’Python Crash Course’, author=’Eric Matthes’) print(len(book)) # 544
- 这些方法让你的对象可以使用比较操作符: class Box: def __init__(self, weight): self.weight = weight def __lt__(self, other): return self.weight < other.weight def __eq__(self, other): return self.weight == other.weight box1 = Box(10) box2 = Box(20) print(box1 < box2) # True print(box1 == box2) # False
- 方法 对应操作符 __add__ + __sub__ – __mul__ * __truediv__ / __pow__ ** 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) def __str__(self): return f”Vector({self.x}, {self.y})” v1 = Vector(1, 2) v2 = Vector(3, 4) print(v1 + v2) # Vector(4, 6)
- class Countdown: def __init__(self, start): self.start = start def __iter__(self): return self def __next__(self): if self.start <= 0: raise StopIteration self.start -= 1 return self.start + 1 for i in Countdown(5): print(i, end=’ ‘) # 5 4 3 2 1
- 方法 功能 __getitem__ 获取元素 (obj[key]) __setitem__ 设置元素 (obj[key] = value) __delitem__ 删除元素 (del obj[key]) __contains__ 成员检查 (key in obj) class SparseList: def __init__(self, size): self.size = size self.data = {} def __getitem__(self, index): if index < 0 or index >= self.size: raise IndexError(“Index out of range”) return self.data.get(index, 0) def __setitem__(self, index, value): if index < 0 or index >= self.size: raise IndexError(“Index out of range”) self.data[index] = value def __contains__(self, value): return value in self.data.values() sparse = SparseList(10) sparse[3] = 42 print(sparse[3]) # 42 print(42 in sparse) # True print(sparse[4]) # 0
- class ProtectedAttributes: def __init__(self): self._protected = “This is protected” def __getattr__(self, name): return f”‘{name}’ attribute not found” def __setattr__(self, name, value): if name.startswith(‘_’): super().__setattr__(name, value) else: raise AttributeError(f”Cannot set attribute ‘{name}'”) obj = ProtectedAttributes() print(obj.nonexistent) # ‘nonexistent’ attribute not found # obj.public = “test” # Raises AttributeError
- class DatabaseConnection: def __enter__(self): print(“Connecting to database…”) return self def __exit__(self, exc_type, exc_val, exc_tb): print(“Closing connection…”) if exc_type: print(f”Error occurred: {exc_val}”) return True # Suppress exceptions with DatabaseConnection() as conn: print(“Executing query…”) # raise ValueError(“Invalid SQL”) # Would be handled by __exit__
- class Counter: def __init__(self): self.count = 0 def __call__(self, increment=1): self.count += increment return self.count counter = Counter() print(counter()) # 1 print(counter(5)) # 6
- class Fraction: def __init__(self, numerator, denominator): self.numerator = numerator self.denominator = denominator def __add__(self, other): new_num = self.numerator * other.denominator + other.numerator * self.denominator new_den = self.denominator * other.denominator return Fraction(new_num, new_den) def __str__(self): return f”{self.numerator}/{self.denominator}” f1 = Fraction(1, 2) f2 = Fraction(1, 3) print(f1 + f2) # 5/6
- class LazyProperty: def __init__(self, func): self.func = func self.name = func.__name__ def __get__(self, obj, type=None): if obj is None: return self value = self.func(obj) setattr(obj, self.name, value) return value class Circle: def __init__(self, radius): self.radius = radius @LazyProperty def area(self): print(“Computing area…”) return 3.14 * self.radius ** 2 c = Circle(5) print(c.area) # First call: computes and caches print(c.area) # Subsequent call: returns cached value
目录
- 什么是魔法函数
- 常用魔法函数分类与功能
- 基础魔法函数
- 比较操作魔法函数
- 算术操作魔法函数
- 迭代器与容器协议
- 迭代器魔法函数
- 容器魔法函数
- 高级魔法函数应用
- 属性访问控制
- 上下文管理器
- 可调用对象
- 性能优化案例
- 实际应用场景
- 1. 实现自定义数值类型
- 2. 构建智能代理对象
- 最佳实践与建议
- 总结
Python中的魔法函数(Magic Methods),也称为双下划线方法(dunder methods),是Python面向对象编程的核心机制之一。它们以__开头和结尾,允许我们自定义类的行为,使其更符合Python的惯用风格。本文将全面介绍这些魔法函数,助你写出更Pythonic的代码。
魔法函数是Python中一类特殊的方法,它们允许你:
- 自定义类的内置行为
- 与Python内置函数/操作符交互
- 实现协议(如迭代器、上下文管理器等)
“Python的魔法函数是其数据模型的核心,它们是框架和Python交互的方式。” – Guido van Rossum
| 方法名 | 功能描述 | 示例 |
|---|---|---|
| __init__ | 构造函数,初始化对象 | obj = MyClass() |
| __str__ | 返回用户友好的字符串表示 | print(obj) |
| __repr__ | 返回开发者友好的字符串表示 | repr(obj) |
| __len__ | 返回容器长度 | len(obj) |
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages
def __str__(self):
return f"'{self.title}' by {self.author}"
def __repr__(self):
return f"Book(title='{self.title}', author='{self.author}')"
def __len__(self):
return self.pages
book = Book("Python Crash Course", "Eric Matthes", 544)
print(book) # 'Python Crash Course' by Eric Matthes
print(repr(book)) # Book(title='Python Crash Course', author='Eric Matthes')
print(len(book)) # 544

这些方法让你的对象可以使用比较操作符:
class Box:
def __init__(self, weight):
self.weight = weight
def __lt__(self, other):
return self.weight < other.weight
def __eq__(self, other):
return self.weight == other.weight
box1 = Box(10)
box2 = Box(20)
print(box1 < box2) # True
print(box1 == box2) # False
| 方法 | 对应操作符 |
|---|---|
| __add__ | + |
| __sub__ | – |
| __mul__ | * |
| __truediv__ | / |
| __pow__ | ** |
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)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)

class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
return self
def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1
for i in Countdown(5):
print(i, end=' ') # 5 4 3 2 1
| 方法 | 功能 |
|---|---|
| __getitem__ | 获取元素 (obj[key]) |
| __setitem__ | 设置元素 (obj[key] = value) |
| __delitem__ | 删除元素 (del obj[key]) |
| __contains__ | 成员检查 (key in obj) |
class SparseList:
def __init__(self, size):
self.size = size
self.data = {}
def __getitem__(self, index):
if index < 0 or index >= self.size:
raise IndexError("Index out of range")
return self.data.get(index, 0)
def __setitem__(self, index, value):
if index < 0 or index >= self.size:
raise IndexError("Index out of range")
self.data[index] = value
def __contains__(self, value):
return value in self.data.values()
sparse = SparseList(10)
sparse[3] = 42
print(sparse[3]) # 42
print(42 in sparse) # True
print(sparse[4]) # 0
class ProtectedAttributes:
def __init__(self):
self._protected = "This is protected"
def __getattr__(self, name):
return f"'{name}' attribute not found"
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
else:
raise AttributeError(f"Cannot set attribute '{name}'")
obj = ProtectedAttributes()
print(obj.nonexistent) # 'nonexistent' attribute not found
# obj.public = "test" # Raises AttributeError

class DatabaseConnection:
def __enter__(self):
print("Connecting to database...")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Closing connection...")
if exc_type:
print(f"Error occurred: {exc_val}")
return True # Suppress exceptions
with DatabaseConnection() as conn:
print("Executing query...")
# raise ValueError("Invalid SQL") # Would be handled by __exit__
class Counter:
def __init__(self):
self.count = 0
def __call__(self, increment=1):
self.count += increment
return self.count
counter = Counter()
print(counter()) # 1
print(counter(5)) # 6
使用__slots__减少内存占用
class RegularPoint:
def __init__(self, x, y):
self.x = x
self.y = y
class SlottedPoint:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
import sys
regular = RegularPoint(1, 2)
slotted = SlottedPoint(1, 2)
print(sys.getsizeof(regular)) # 56 bytes (approx)
print(sys.getsizeof(slotted)) # 32 bytes (approx)
性能提示:__slots__可以显著减少大量实例的内存使用,但会限制动态属性添加【1†source】。
class Fraction:
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator
def __add__(self, other):
new_num = self.numerator * other.denominator + other.numerator * self.denominator
new_den = self.denominator * other.denominator
return Fraction(new_num, new_den)
def __str__(self):
return f"{self.numerator}/{self.denominator}"
f1 = Fraction(1, 2)
f2 = Fraction(1, 3)
print(f1 + f2) # 5/6
class LazyProperty:
def __init__(self, func):
self.func = func
self.name = func.__name__
def __get__(self, obj, type=None):
if obj is None:
return self
value = self.func(obj)
setattr(obj, self.name, value)
return value
class Circle:
def __init__(self, radius):
self.radius = radius
@LazyProperty
def area(self):
print("Computing area...")
return 3.14 * self.radius ** 2
c = Circle(5)
print(c.area) # First call: computes and caches
print(c.area) # Subsequent call: returns cached value
- 一致性原则:实现比较方法时,确保
__eq__和__hash__一致【2†source】
- 文档字符串:为魔法函数提供清晰的文档说明
- 错误处理:在魔法函数中提供有意义的错误信息
- 性能考虑:对于性能关键代码,考虑使用
__slots__或C扩展
- 协议完整性:实现协议时,确保所有必要方法都已实现
# 好的实践示例
class GoodExample:
"""遵循最佳实践的类实现"""
def __init__(self, value):
self._value = value
def __repr__(self):
return f"{self.__class__.__name__}({self._value!r})"
def __str__(self):
return f"Value: {self._value}"
def __eq__(self, other):
if not isinstance(other, GoodExample):
return NotImplemented
return self._value == other._value
def __hash__(self):
return hash(self._value)
__eq__和__hash__一致【2†source】__slots__或C扩展
Python的魔法函数提供了一套强大的工具,让我们能够:
- 自定义对象行为
- 与Python内置机制无缝集成
- 编写更直观、Pythonic的代码
- 构建高性能、可维护的系统
掌握魔法函数是每个Python开发者从初级走向高级的必经之路。它们不仅仅是语法糖,更是Python数据模型的核心实现机制。
“简单比复杂更好,但复杂比混乱更好。” – Tim Peters
通过合理使用魔法函数,我们可以在保持代码简洁的同时,实现复杂而优雅的功能
到此这篇关于一文浅析Python中常用的魔法函数使用指南的文章就介绍到这了,更多相关Python魔法函数内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- Python中的魔法函数和魔法属性用法示例
- 16个python常用魔法函数小结
- 详解Python中的魔法函数与量子计算模拟
- Python学习之魔法函数(filter,map,reduce)详解
- 图文详解Python中最神秘的一个魔法函数
- 在Python中画图(基于Jupyter notebook的魔法函数)
- python 魔法函数实例及解析