一文淺析Python中常用的魔法函數(shù)使用指南
Python中的魔法函數(shù)(Magic Methods),也稱為雙下劃線方法(dunder methods),是Python面向?qū)ο缶幊痰暮诵臋C制之一。它們以__開頭和結(jié)尾,允許我們自定義類的行為,使其更符合Python的慣用風(fēng)格。本文將全面介紹這些魔法函數(shù),助你寫出更Pythonic的代碼。
什么是魔法函數(shù)
魔法函數(shù)是Python中一類特殊的方法,它們允許你:
- 自定義類的內(nèi)置行為
- 與Python內(nèi)置函數(shù)/操作符交互
- 實現(xiàn)協(xié)議(如迭代器、上下文管理器等)
“Python的魔法函數(shù)是其數(shù)據(jù)模型的核心,它們是框架和Python交互的方式。” - Guido van Rossum
常用魔法函數(shù)分類與功能
基礎(chǔ)魔法函數(shù)
| 方法名 | 功能描述 | 示例 |
|---|---|---|
| __init__ | 構(gòu)造函數(shù),初始化對象 | obj = MyClass() |
| __str__ | 返回用戶友好的字符串表示 | print(obj) |
| __repr__ | 返回開發(fā)者友好的字符串表示 | 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
比較操作魔法函數(shù)

這些方法讓你的對象可以使用比較操作符:
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
算術(shù)操作魔法函數(shù)
| 方法 | 對應(yīng)操作符 |
|---|---|
| __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)
迭代器與容器協(xié)議
迭代器魔法函數(shù)

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
容器魔法函數(shù)
| 方法 | 功能 |
|---|---|
| __getitem__ | 獲取元素 (obj[key]) |
| __setitem__ | 設(shè)置元素 (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
高級魔法函數(shù)應(yīng)用
屬性訪問控制
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__
可調(diào)用對象
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
性能優(yōu)化案例
使用__slots__減少內(nèi)存占用
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__可以顯著減少大量實例的內(nèi)存使用,但會限制動態(tài)屬性添加【1†source】。
實際應(yīng)用場景
1. 實現(xiàn)自定義數(shù)值類型
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
2. 構(gòu)建智能代理對象
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
最佳實踐與建議
- 一致性原則:實現(xiàn)比較方法時,確保
__eq__和__hash__一致【2†source】 - 文檔字符串:為魔法函數(shù)提供清晰的文檔說明
- 錯誤處理:在魔法函數(shù)中提供有意義的錯誤信息
- 性能考慮:對于性能關(guān)鍵代碼,考慮使用
__slots__或C擴展 - 協(xié)議完整性:實現(xiàn)協(xié)議時,確保所有必要方法都已實現(xiàn)
# 好的實踐示例
class GoodExample:
"""遵循最佳實踐的類實現(xiàn)"""
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)
總結(jié)
Python的魔法函數(shù)提供了一套強大的工具,讓我們能夠:
- 自定義對象行為
- 與Python內(nèi)置機制無縫集成
- 編寫更直觀、Pythonic的代碼
- 構(gòu)建高性能、可維護的系統(tǒng)
掌握魔法函數(shù)是每個Python開發(fā)者從初級走向高級的必經(jīng)之路。它們不僅僅是語法糖,更是Python數(shù)據(jù)模型的核心實現(xiàn)機制。
“簡單比復(fù)雜更好,但復(fù)雜比混亂更好。” - Tim Peters
通過合理使用魔法函數(shù),我們可以在保持代碼簡潔的同時,實現(xiàn)復(fù)雜而優(yōu)雅的功能
到此這篇關(guān)于一文淺析Python中常用的魔法函數(shù)使用指南的文章就介紹到這了,更多相關(guān)Python魔法函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python基于pyjnius庫實現(xiàn)訪問java類
這篇文章主要介紹了Python基于pyjnius庫實現(xiàn)訪問java類,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07
Django中利用filter與simple_tag為前端自定義函數(shù)的實現(xiàn)方法
這篇文章主要給大家介紹了Django中利用filter與simple_tag為前端自定義函數(shù)的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-06-06
Python requests請求響應(yīng)以流stream的方式實現(xiàn)打印輸出
在使用requests庫時,接收響應(yīng)并打印內(nèi)容需注意:若響應(yīng)內(nèi)容過大,應(yīng)設(shè)置合理的chunk_size參數(shù)以避免內(nèi)存溢出,當(dāng)設(shè)置了stream=True時,不能使用response.text或response.content屬性讀取響應(yīng)內(nèi)容,否則會拋出異常2025-10-10
一文詳解Python灰色預(yù)測模型實現(xiàn)示例
這篇文章主要為大家介紹了Python灰色預(yù)測模型實現(xiàn)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02

