选举预测中的信号解码:机器学习在政治系统建模中的实践框架
2026/6/9 11:10:56
Python中的魔法函数(Magic Methods),也称为双下划线方法(dunder methods),是Python面向对象编程的核心机制之一。它们以
__开头和结尾,允许我们自定义类的行为,使其更符合Python的惯用风格。本文将全面介绍这些魔法函数,助你写出更Pythonic的代码。
魔法函数是Python中一类特殊的方法,它们允许你:
“Python的魔法函数是其数据模型的核心,它们是框架和Python交互的方式。” - Guido van Rossum
| 方法名 | 功能描述 | 示例 |
|---|---|---|
__init__ | 构造函数,初始化对象 | obj = MyClass() |
__str__ | 返回用户友好的字符串表示 | print(obj) |
__repr__ | 返回开发者友好的字符串表示 | repr(obj) |
__len__ | 返回容器长度 | len(obj) |
classBook:def__init__(self,title,author,pages):self.title=title self.author=author self.pages=pagesdef__str__(self):returnf"'{self.title}' by{self.author}"def__repr__(self):returnf"Book(title='{self.title}', author='{self.author}')"def__len__(self):returnself.pages book=Book("Python Crash Course","Eric Matthes",544)print(book)# 'Python Crash Course' by Eric Matthesprint(repr(book))# Book(title='Python Crash Course', author='Eric Matthes')print(len(book))# 544这些方法让你的对象可以使用比较操作符:
classBox:def__init__(self,weight):self.weight=weightdef__lt__(self,other):returnself.weight<other.weightdef__eq__(self,other):returnself.weight==other.weight box1=Box(10)box2=Box(20)print(box1<box2)# Trueprint(box1==box2)# False| 方法 | 对应操作符 |
|---|---|
__add__ | + |
__sub__ | - |
__mul__ | * |
__truediv__ | / |
__pow__ | ** |
classVector:def__init__(self,x,y):self.x=x self.y=ydef__add__(self,other):returnVector(self.x+other.x,self.y+other.y)def__str__(self):returnf"Vector({self.x},{self.y})"v1=Vector(1,2)v2=Vector(3,4)print(v1+v2)# Vector(4, 6)classCountdown:def__init__(self,start):self.start=startdef__iter__(self):returnselfdef__next__(self):ifself.start<=0:raiseStopIteration self.start-=1returnself.start+1foriinCountdown(5):print(i,end=' ')# 5 4 3 2 1| 方法 | 功能 |
|---|---|
__getitem__ | 获取元素 (obj[key]) |
__setitem__ | 设置元素 (obj[key] = value) |
__delitem__ | 删除元素 (del obj[key]) |
__contains__ | 成员检查 (key in obj) |
classSparseList:def__init__(self,size):self.size=size self.data={}def__getitem__(self,index):ifindex<0orindex>=self.size:raiseIndexError("Index out of range")returnself.data.get(index,0)def__setitem__(self,index,value):ifindex<0orindex>=self.size:raiseIndexError("Index out of range")self.data[index]=valuedef__contains__(self,value):returnvalueinself.data.values()sparse=SparseList(10)sparse[3]=42print(sparse[3])# 42print(42insparse)# Trueprint(sparse[4])# 0classProtectedAttributes:def__init__(self):self._protected="This is protected"def__getattr__(self,name):returnf"'{name}' attribute not found"def__setattr__(self,name,value):ifname.startswith('_'):super().__setattr__(name,value)else:raiseAttributeError(f"Cannot set attribute '{name}'")obj=ProtectedAttributes()print(obj.nonexistent)# 'nonexistent' attribute not found# obj.public = "test" # Raises AttributeErrorclassDatabaseConnection:def__enter__(self):print("Connecting to database...")returnselfdef__exit__(self,exc_type,exc_val,exc_tb):print("Closing connection...")ifexc_type:print(f"Error occurred:{exc_val}")returnTrue# Suppress exceptionswithDatabaseConnection()asconn:print("Executing query...")# raise ValueError("Invalid SQL") # Would be handled by __exit__classCounter:def__init__(self):self.count=0def__call__(self,increment=1):self.count+=incrementreturnself.count counter=Counter()print(counter())# 1print(counter(5))# 6__slots__减少内存占用classRegularPoint:def__init__(self,x,y):self.x=x self.y=yclassSlottedPoint:__slots__=['x','y']def__init__(self,x,y):self.x=x self.y=yimportsys 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】。
classFraction:def__init__(self,numerator,denominator):self.numerator=numerator self.denominator=denominatordef__add__(self,other):new_num=self.numerator*other.denominator+other.numerator*self.denominator new_den=self.denominator*other.denominatorreturnFraction(new_num,new_den)def__str__(self):returnf"{self.numerator}/{self.denominator}"f1=Fraction(1,2)f2=Fraction(1,3)print(f1+f2)# 5/6classLazyProperty:def__init__(self,func):self.func=func self.name=func.__name__def__get__(self,obj,type=None):ifobjisNone:returnself value=self.func(obj)setattr(obj,self.name,value)returnvalueclassCircle:def__init__(self,radius):self.radius=radius@LazyPropertydefarea(self):print("Computing area...")return3.14*self.radius**2c=Circle(5)print(c.area)# First call: computes and cachesprint(c.area)# Subsequent call: returns cached value__eq__和__hash__一致【2†source】__slots__或C扩展# 好的实践示例classGoodExample:"""遵循最佳实践的类实现"""def__init__(self,value):self._value=valuedef__repr__(self):returnf"{self.__class__.__name__}({self._value!r})"def__str__(self):returnf"Value:{self._value}"def__eq__(self,other):ifnotisinstance(other,GoodExample):returnNotImplementedreturnself._value==other._valuedef__hash__(self):returnhash(self._value)Python的魔法函数提供了一套强大的工具,让我们能够:
掌握魔法函数是每个Python开发者从初级走向高级的必经之路。它们不仅仅是语法糖,更是Python数据模型的核心实现机制。
“简单比复杂更好,但复杂比混乱更好。” - Tim Peters
通过合理使用魔法函数,我们可以在保持代码简洁的同时,实现复杂而优雅的功能【1†source】【2†source】。
参考资料: