
上个月重构老项目,翻出一堆写了又删的代码。有个类光是初始化参数就十几个,每次实例化都像在填表格。
后来我花了一晚上研究魔法方法,改完自己都吓了一跳。同样的功能,代码量少了三分之一,同事看我的眼神都不太一样了。
先说 __new__ 和 __init__ 的分工。以前我总把创建逻辑全塞进初始化里,后来才明白,__new__ 管的是“造出个啥”,__init__ 管的是“造出来之后怎么打扮”。做单例模式的时候,重写 __new__ 比写装饰器直观多了,直接控制实例的诞生过程。
共享配置对象的时候,这段代码帮我省了好几次数据库连接。
class Config:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
看着简单,但每次调用都拿到同一个对象,不用再担心全局变量被到处改。
__getattr__ 这个魔法方法救了我一次。有个老接口返回的字段名是动态的,有些对象有 user_name,有些只有 name。写一堆 if 判断太蠢了,我就用 __getattr__ 做了一层兜底。
def __getattr__(self, item):
if item == 'user_name' and hasattr(self, 'name'):
return self.name
raise AttributeError(f'{item} not found')
这样不管外部传什么字段名,我都能拿到正确的值。调用方不用知道内部字段命名差异,代码干净得像没处理过一样。
再说 __setattr__。我以前写数据校验,每个 setter 方法都写一遍长度检查。后来直接在 __setattr__ 里拦一道,所有属性赋值都走同一个规则。
def __setattr__(self, key, value):
if key == 'phone' and len(value) != 11:
raise ValueError('手机号必须11位')
super().__setattr__(key, value)
比在每个属性上写 property 快多了,改起来也省事,只动一个地方。
有个场景让我印象特别深。同事写了个日志类,每次打印都要拼时间戳和级别。后来我给他加了 __str__ 和 __repr__ 的组合,让对象自己会说话。
def __str__(self):
return f'[{self.level}] {self.msg}'
def __repr__(self):
return f'Log({self.level!r}, {self.msg!r})'
调试的时候直接 print(log_obj),看到的不是内存地址,是一眼能看懂的内容。信息直接印在对象上,比任何文档都清楚。
__enter__ 和 __exit__ 就不用多说了,写资源管理的类,文件、连接、锁,都靠它们收尾。以前我总忘了 close,现在 with 语句一结束,资源自动释放,不用惦记。
class FileReader:
def __enter__(self):
self.file = open(self.path, 'r')
return self.file
def __exit__(self, args):
self.file.close()
这段代码大概写了十几次了,每次都能帮我省掉排查资源泄漏的时间。
最后是 __call__。啥时候用呢,就是你想让一个对象看起来像个函数。之前写个回调处理器,一堆选项参数塞在构造函数里,调用时还得传个配置字典。改成 __call__ 之后,直接 handler(data) 就行,外部调用方根本不用知道内部怎么组织的。
def __call__(self, data):
return self.process(data)
这种写法让接口变薄了,依赖变少了,改动成本跟着降了。
还有个小技巧,用 __iter__ 让对象可以直接放进 for 循环。以前写个数据分页类,每次都要手动取下一批,现在直接 for item in pager,内部自动翻页。代码读起来像在说人话,不用猜内部机制。
魔法方法不是炫技,是让你把重复逻辑收拢到一个地方。我见过太多人为了“好看”写一堆装饰器,结果层层包裹谁也看不懂。真正的优雅是让调用方感觉不到你的存在,数据给进去,结果拿出来,中间发生了什么,那不是调用方的事。
写类的时候,多想想哪些行为是 对象天生就该有的。比如比较大小用 __lt__,求长度用 __len__,这样你的类跟语言本身的特性就能咬合上,别人用起来也顺手。
别怕试,找个旧模块重构一下,把那些 if-else 挤掉的校验逻辑搬进魔法方法里。等你发现改动量变小了,测试用例不用跟着改,你就尝到甜头了。
以上就是“自从学会这几个魔法方法,我的Python类写得更优雅了!”的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。
扫码二维码 获取免费视频学习资料

- 本文固定链接: http://www.phpxs.com/post/14468/
- 转载请注明:转载必须在正文中标注并保留原文链接
- 扫码: 扫上方二维码获取免费视频资料