Pyhton魔术方法与Java整理
Pyhton魔术方法与Java整理
- 第一类:对象的“生老病死”(构造与析构)
- 第二类:把自己伪装成“函数”
- 第三类:字符串表示(调试神器)
- 第四类:把自己伪装成“容器”(列表/字典)
- 第五类:运算符重载(数学与比较)
- 第六类:属性访问控制(Getter/Setter)
- 第七类:上下文管理器(With语句)
- 总结:一张表看懂 Python 的“潜规则”
Python 里这些被双下划线包裹的方法,官方名叫 Magic Methods(魔术方法),社区常叫 Dunder Methods(双下方法)。它们很像 Java 里的“特殊方法”,但比 Java 多得多,也更自由。
如果把 Java 比作“规矩森严的工厂”,Python 的这些魔术方法就是给对象开的“后门”,让你能伪装成内置类型(比如假装自己是函数、列表、字典)。
以下是 Python 中最核心、最常用的魔术方法分类大全,我特意加了大量 Java 对比,方便你理解:
第一类:对象的“生老病死”(构造与析构)
这是“构造函数”家族。
| 方法 | 类比 | Java 含义 |
|---|---|---|
| _name _() | - | 区分「文件是被直接运行,还是被导入」 |
| _new _(cls, …) | - | 真正的构造函数(创建对象)。极少重写,多用于单例模式或不可变对象。 |
| _init _(self, …) | 构造函数ClassName() | 初始化函数。对象创建后自动调用,用来赋初值。 |
| _del _(self) | finalize() 析构函数。 | 对象被垃圾回收前调用(不推荐依赖它,因为GC时机不确定)。 |
Python 特色:__new __ 和 __init __ 分离。
• __new __ 负责“生孩子”(分配内存,返回对象)。
• __init __ 负责“养孩子”(给对象穿衣服、起名字)。
• __name __ Python 解释器运行一个.py文件时,会自动给这个文件对应的模块对象设置__name __属性:如果直接运行这个文件(比如python test.py):__name __会被设为字符串"__main __“。如果这个文件被其他文件import(比如import test):test.py的__name __就是文件名"test”。
最经典的用法:if __name __ == “__main __”:
第二类:把自己伪装成“函数”
| 方法 | 类比 | Java 含义 |
|---|---|---|
| __call __(self, …) | Functional Interface | 让实例变得可调用。定义了这个方法,对象就能像函数一样加括号执行:obj() |
第三类:字符串表示(调试神器)
Java 里靠@Override toString(),Python 有两个,分工明确。
| 方法 | 类比 | Java 含义 |
|---|---|---|
| __str __(self) | toString() | 给用户看。执行 print(obj) 或 str(obj) 时调用。追求可读性。 |
| __repr __(self) | toString() (调试版) | 给开发者看。直接输入 obj 回车时调用。追求准确性(最好能用来重建对象)。 |
潜规则:如果只写一个,就写 __repr __。
第四类:把自己伪装成“容器”(列表/字典)
这是 Python 比 Java 灵活得多的一个地方。你可以让一个对象支持 obj[key]、len(obj) 这种操作。
| 方法 | 类比 | Java 含义 |
|---|---|---|
| __len __(self) | size() / length() | 定义 len(obj) 的行为。 |
| __getitem __(self, key) | get(index) / get(key) | 定义 obj[key] 的读取行为。 |
| __setitem __(self, key, val) | put(index, val) | 定义 obj[key] = val 的写入行为。 |
| __contains __(self, item) | contains() | 定义 in 运算符的行为 (if x in obj)。 |
第五类:运算符重载(数学与比较)
Java 不允许运算符重载(除了 + 拼接字符串),Python 允许。
| 方法 | 运算符 | 含义 |
|---|---|---|
| __add __(self, other) | + | 加法 |
| __sub __(self, other) | - | 减法 |
| __eq __(self, other) | == | 相等 |
| __lt __(self, other) | < | 小于 |
| __gt __(self, other) | > | 大于 |
例子:
classVector:def__init__(self,x):self.x=xdef__add__(self,other):returnVector(self.x+other.x)v1=Vector(1)v2=Vector(2)v3=v1+v2# 这里自动调用 __add__第六类:属性访问控制(Getter/Setter)
Java 里用 getX() 和 setX(),Python 用装饰器,但底层是这些方法。
| 方法 | 类比 | Java 含义 |
|---|---|---|
| __getattr __(self, name) | - | 访问不存在的属性时调用(常用于动态代理)。 |
| __setattr __(self, name, val) | Setter | 设置属性时调用(慎用,容易死循环)。 |
| __getattribute __(self, name) | Getter | 访问任何属性时调用(比getattr更底层)。 |
第七类:上下文管理器(With语句)
对应 Java 的 try-with-resources。
| 方法 | 类比 | Java 含义 |
|---|---|---|
| __enter __(self) | try(…) | 进入 with 代码块时调用。 |
| __exit __(self, …) | catch/finally | 退出 with 代码块时调用(无论是否异常)。 |
例子:
withopen('file.txt')asf:data=f.read()这里自动调用了 f.__enter __() 和 f.__exit __()
总结:一张表看懂 Python 的“潜规则”
- 如果你想让对象实现这个方法
- 像函数一样被调用 __call __
- 用 print() 打印好看 __str __
- 用 len() 取长度 __len __
- 用 obj[key] 取值 __getitem __
- 用 obj1 + obj2 相加 __add __
- 用 with 管理资源 __enter __, __exit __
- 支持 for…in… 循环 __iter __, __next __
一句话总结:Java 的“特殊方法”是语言规定死的;Python 的魔术方法是开放的协议,只要你实现了特定的双下方法,你的对象就能获得对应的“超能力”。
