鸭子类型是动态语言的类型哲学:"如果它走起来像鸭子、叫起来像鸭子,那它就是鸭子。"对象的类型不重要,重要的是它有没有你需要的方法/属性。代码只依赖行为协议而非继承关系。

def quack(creature):
    creature.quack()   # 不关心 creature 是什么类,能 quack 就行

Python 的协议(可迭代、上下文管理器、序列)都是鸭子类型的体现:for 循环不要求对象是 list,只要实现 __iter__

与接口(Java/Go 风格)的异同

  • 相同点:都是面向"行为契约"编程,实现多态、解耦调用方与实现方。
  • 不同点:接口是显式、静态的——编译期检查,必须先声明实现关系,文档和契约清晰;鸭子类型是隐式、动态的——无需声明、灵活易扩展(猴子补丁、第三方对象直接可用),但错误延迟到运行期才暴露(AttributeError),契约靠文档和约定,重构时缺乏编译器保护。
  • 折中方案:Python 提供 abc 抽象基类(可虚拟子类化,isinstance 检查)和 typing.Protocol(结构化类型检查,让 mypy 在静态层面验证鸭子类型),兼顾灵活与安全。

追问方向:EAFP 与鸭子类型的关系、Protocol 与 ABC 的取舍、鸭子类型的测试策略。