面向对象:更少的仪式,更多的协议
record → dataclass,interface → Protocol,getter/setter → @property。Python 的 OOP 是减法。
18 分钟 · 右栏代码可点击「运行」
类与构造器:self 是显式的
Java
1public class Person {2 private final String name;3 private int age;45 public Person(String name, int age) {6 this.name = name;7 this.age = age;8 }9 public String getName() { return name; }10}
Python
1class Person:2 def __init__(self, name: str, age: int):3 self.name = name # 属性默认公开4 self.age = age56p = Person("Ada", 36)7print(p.name) # 直接访问,没有 getter
self等价于this,但必须显式写在参数列表第一位;调用时不用传(p.name自动绑定)。- 需要拦截读写时再加
@property,调用方代码完全不用改 —— 这就是为什么 Python 不鼓励一开始就写 getter/setter。
record → dataclass(一行消灭样板)
Java
1// Java 16+2public record Point(int x, int y) {}34// 旧写法:private 字段 + 构造器5// + equals + hashCode + toString ≈ 40 行
Python
1from dataclasses import dataclass23@dataclass4class Point:5 x: int6 y: int78# 自动生成 __init__ / __eq__ / __repr__9p = Point(1, 2)10print(p) # Point(x=1, y=2)11# 不可变:@dataclass(frozen=True)
interface → Protocol(结构化,像 Go 但有静态检查)
Java
1interface Closer {2 void close();3}45// 必须显式 implements6class File implements Closer {7 public void close() { ... }8}
Python
1from typing import Protocol23class Closer(Protocol):4 def close(self) -> None: ...56# 不需要继承:任何有 close() 的对象7# 都满足 Closer(静态鸭子类型)89def cleanup(c: Closer) -> None:10 c.close()
- Protocol 是 Go 隐式接口的 Python 版,但 mypy/pyright 会在静态阶段报错 —— 鸭子类型的编译期保险。
- 需要运行时强制继承体系时才用
abc.ABC+@abstractmethod。
继承与组合
Java
1public class Admin extends User {2 public Admin(String name) {3 super(name);4 }5 @Override6 public String describe() {7 return "Admin:" + getName();8 }9}
Python
1class Admin(User):2 def __init__(self, name: str):3 super().__init__(name)45 def describe(self) -> str: # 覆写不需要注解6 return f"Admin:{self.name}"
- Python 遵循 EAFP 与组合优先,但继承语法本身很轻。多继承合法(MRO 顺序解析),Java 式 interface 多实现用 Protocol 组合。
注意
Java 习惯最大的坏味道 — 把所有字段设为私有再生成 getter/setter。Python 惯例:直接公开属性,出现校验/派生逻辑时无痛升级为 @property。
练一练
这张卡的示例代码已在游乐场中备好,改一改再运行。