Python魔术方法是对象行为的底层控制开关,非语法糖;必须重写__new__实现单例、不可变类型子类或多元构造;__eq__与__hash__需成对定义以支持集合操作;__enter__和__exit__使类支持with语句。

Python 魔术方法不是语法糖,而是对象行为的底层控制开关——你定义了 __str__,print() 就走它;没实现 __eq__,两个自定义实例默认按内存地址比,哪怕所有属性都一样也返回 False。
什么时候必须重写 __init__ 和 __new__
__init__ 是初始化钩子,负责给刚创建的对象赋值;__new__ 才是真正的构造器,负责返回实例本身。多数场景只用 __init__,但以下情况绕不开 __new__:
- 单例模式:在
__new__里检查类变量是否已有实例,有则直接返回,不调用__init__ - 不可变类型子类(如继承
str或tuple):__init__无法修改实例状态,必须在__new__中完成值的预处理 - 从不同数据源构造对象:比如一个
Config类,既支持Config.from_json(...)又支持Config.from_env(...),统一收口到__new__更干净
__eq__、__hash__ 和集合操作的关系
只要用了 set、dict 键或 in 判断,就绕不开这两个方法。默认情况下,所有自定义类实例都是可哈希的(id() 为 hash),且 == 等价于 is。这通常不是你想要的:
- 如果重写了
__eq__却没重写__hash__,实例会自动变成不可哈希(TypeError: unhashable type),进不了set或当dict键 - 若逻辑上对象应“值相等即等价”(比如两个
User(id=1, name='a')应视为同一人),需同时定义:def __eq__(self, other): return isinstance(other, User) and self.id == other.id def __hash__(self): return hash(self.id) - 注意:一旦定义了
__hash__,对象就应是不可变的——否则把实例放进set后改了id,哈希值变了,set内部就找不到了
让类支持 with 语句的关键是 __enter__ 和 __exit__
这不是装饰器或上下文管理器库的专利,而是语言级协议。只要实现了这两个方法,就能用 with 自动管理资源生命周期:
飞蛙B2B2C(FeiWa B2B2C)商城系统是山东破浪网络科技有限公司于2017年最新推出的企业级B2B2C电商平台系统,采用PHP5+MySQL技术为基础,OOP(面向对象)方式进行核心框架搭建,结合MVC模式进行开发,可以支持Windows/Unix服务器环境,需PHP5.3及以上版本支持,可运行于包括Apache、IIS和Nginx在内的多种WEB服务器。飞蛙B2B2C(FeiWa B2
立即学习“Python免费学习笔记(深入)”;
-
__enter__返回什么,as就绑定什么(常返回self,也可返回其他对象) -
__exit__(exc_type, exc_value, traceback)的三个参数分别对应异常类型、值、回溯;返回True表示“已处理异常,不往外抛”,返回None或False表示继续传播 - 常见误操作:在
__exit__里直接raise新异常,会覆盖原始异常;如需补日志又不想吞异常,应显式return False并记录 - 文件、数据库连接、锁等资源类,用这个比手动
try/finally更可靠,也更符合 Python 习惯
魔术方法不是炫技工具,它们是 Python 对象模型的接口契约。漏掉一个 __bool__,if obj: 就永远为真;忘了 __len__,连 len(obj) 都报 TypeError。真正麻烦的不是写法,而是不写时那些隐晦的行为偏差——比如测试通过,上线后字典键冲突,或者 with 块里异常静默消失。







