一文淺析Python中常用的魔法函數(shù)使用指南
Python中的魔法函數(shù)(Magic Methods),也稱為雙下劃線方法(dunder methods),是Python面向?qū)ο缶幊痰暮诵臋C(jī)制之一。它們以__開頭和結(jié)尾,允許我們自定義類的行為,使其更符合Python的慣用風(fēng)格。本文將全面介紹這些魔法函數(shù),助你寫出更Pythonic的代碼。
什么是魔法函數(shù)
魔法函數(shù)是Python中一類特殊的方法,它們允許你:
- 自定義類的內(nèi)置行為
- 與Python內(nèi)置函數(shù)/操作符交互
- 實(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__可以顯著減少大量實(shí)例的內(nèi)存使用,但會限制動態(tài)屬性添加【1†source】。
實(shí)際應(yīng)用場景
1. 實(shí)現(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
最佳實(shí)踐與建議
- 一致性原則:實(shí)現(xiàn)比較方法時(shí),確保
__eq__和__hash__一致【2†source】 - 文檔字符串:為魔法函數(shù)提供清晰的文檔說明
- 錯誤處理:在魔法函數(shù)中提供有意義的錯誤信息
- 性能考慮:對于性能關(guān)鍵代碼,考慮使用
__slots__或C擴(kuò)展 - 協(xié)議完整性:實(shí)現(xiàn)協(xié)議時(shí),確保所有必要方法都已實(shí)現(xiàn)
# 好的實(shí)踐示例
class GoodExample:
"""遵循最佳實(shí)踐的類實(shí)現(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ù)提供了一套強(qiáng)大的工具,讓我們能夠:
- 自定義對象行為
- 與Python內(nèi)置機(jī)制無縫集成
- 編寫更直觀、Pythonic的代碼
- 構(gòu)建高性能、可維護(hù)的系統(tǒng)
掌握魔法函數(shù)是每個Python開發(fā)者從初級走向高級的必經(jīng)之路。它們不僅僅是語法糖,更是Python數(shù)據(jù)模型的核心實(shí)現(xiàn)機(jī)制。
“簡單比復(fù)雜更好,但復(fù)雜比混亂更好。” - Tim Peters
通過合理使用魔法函數(shù),我們可以在保持代碼簡潔的同時(shí),實(shí)現(xiàn)復(fù)雜而優(yōu)雅的功能
到此這篇關(guān)于一文淺析Python中常用的魔法函數(shù)使用指南的文章就介紹到這了,更多相關(guān)Python魔法函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 實(shí)現(xiàn)圖片色彩轉(zhuǎn)換案例
我們在看動漫、影視作品中,當(dāng)人物在回憶過程中,體現(xiàn)出來的畫面一般都是黑白或者褐色的。本文將提供將圖片色彩轉(zhuǎn)為黑白或者褐色風(fēng)格的案例詳解,感興趣的小伙伴可以了解一下。2021-11-11
python使用xlrd和xlwt讀寫Excel文件的實(shí)例代碼
這篇文章主要介紹了python使用xlrd和xlwt讀寫Excel文件的實(shí)例代碼,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09
利用pyshp包給shapefile文件添加字段的實(shí)例
今天小編就為大家分享一篇利用pyshp包給shapefile文件添加字段的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
Python裝飾器類方法擴(kuò)展元類管理實(shí)例探究
這篇文章主要為大家介紹了Python裝飾器類方法擴(kuò)展元類管理實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Python內(nèi)置函數(shù)map()的具體使用
Python中的map()函數(shù)是一個高效的內(nèi)置函數(shù),用于將指定函數(shù)應(yīng)用于序列的每個元素,通過接收一個函數(shù)和一個或多個序列,本文就來詳細(xì)的介紹一下如何使用,感興趣的可以了解一下2024-09-09
python3.6.5基于kerberos認(rèn)證的hive和hdfs連接調(diào)用方式
這篇文章主要介紹了python3.6.5基于kerberos認(rèn)證的hive和hdfs連接調(diào)用方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06

