在 Python 中,“鸭子多态”通常指的是通过鸭子类型实现的多态行为。它不是一种独立的技术,而是 Python 动态类型特性带来的编程风格。

核心概念:鸭子类型

“如果它走路像鸭子,叫起来像鸭子,那么它就是鸭子。”

在 Python 中,一个对象的适用性取决于它是否具有所需的方法和属性,而不是它的实际类型。不需要显式继承同一个父类或实现同一个接口。

与静态语言多态的区别

静态语言(如 Java/C++) Python(鸭子类型)
多态依赖继承接口实现 多态依赖对象行为(方法存在即可)
必须显式声明类型关系 运行时动态检查方法
类型检查在编译期完成 类型检查在运行时进行(AttributeError

简单示例

class Duck:
    def quack(self):
        print("嘎嘎嘎")

class Person:
    def quack(self):
        print("我在模仿鸭子叫:嘎嘎嘎")

class Dog:
    def bark(self):
        print("汪汪汪")

def make_it_quack(thing):
    """不关心 thing 是什么类型,只关心它能不能 quack"""
    thing.quack()

# 使用
duck = Duck()
person = Person()
dog = Dog()

make_it_quack(duck)    # 输出:嘎嘎嘎
make_it_quack(person)  # 输出:我在模仿鸭子叫:嘎嘎嘎
# make_it_quack(dog)   # 报错 AttributeError,因为 Dog 没有 quack 方法

优点与注意事项

优点:

  • 代码极其灵活,减少样板代码(无需为了复用而强行继承)
  • 鼓励编写基于“协议”(如 __iter____len__)的通用代码

注意事项(也是缺点):

  • 运行时错误风险:如果传入的对象没有所需方法,会在运行时抛出 AttributeError
  • 可读性降低:需要依靠文档或注释说明函数期望的“隐式接口”

常见的“鸭子协议”举例

Python 内置的很多功能都依赖鸭子类型,例如:

  • 可迭代对象:只要定义了 __iter__()__getitem__()for 循环就能处理它。
  • 上下文管理器:只要定义了 __enter__()__exit__(),就能用 with 语句。
  • 文件类对象:只要实现了 read() / write(),就能传给 json.load() 等函数。

这种“行为决定身份”的思想,正是 Python 多态的精髓。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐